我有一个加载结果的搜索表。除了在表单字段中选择的值以外,所有内容都以Redux状态更新。
可以说,下面的搜索显示3条结果。用户单击结果#2,但不喜欢它。单击后退按钮,但表单状态已清除。如何避免这种情况并确保表单状态保持不变?
我将结果存储在Redux中并能够加载,但不确定如何处理状态。我不想使用redux-form之类的软件包,因为这是我唯一需要存储表单状态的地方。
当我更改选择时,状态不会更新。对于专家来说,这可能是对代码的微小更改,但我是初学者,这是我的第一个React-Redux应用程序。
此外,当我离开页面时,不会保留上次存储的状态。这可能是由于我正在初始化的本地状态formValues: {}
所致,但是如果没有此状态,则会出现错误。我试图删除本地状态,仅使用道具,但这在选择框的这一行给了我错误-value={this.state.formValues['gender']}
这是组件的整体代码:
import React, { Component } from 'react'
import { get } from 'axios'
import { connect } from 'react-redux'
import { FadeIn } from 'animate-components'
import {
getSearchResults,
setSearchedOnce,
setPageNum,
setFormValues,
} from '../../actions/searchresults'
import SearchResult from './Result/searchResult'
import SearchNoResult from './Result/searchNoResult'
class SearchAdvanced extends Component {
constructor(props) {
super(props)
this.state = { searchedOnce: false, users: [] }
}
handleChange(event) {
event.preventDefault()
this.props.setFormValues(this.props.formValues)
}
handleSubmit(event) {
event.preventDefault()
this.props.setSearchedOnce(true)
const apiSearchURL = `/api/search/religion/${this.props.formValues.religion}/gender/${this.props.formValues.gender}`
get(apiSearchURL, { maxContentLength: 400 })
.then((searchResults) => {
this.props.getSearchResults(searchResults)
})
}
loadMoreClick() {
this.props.setPageNum(this.props.pageNo + 1)
}
render() {
const { users } = this.props
let mapPageNo = this.props.pageNo
let map_usersList = users.data && users.data.slice(0, mapPageNo * 2).map((userlist => (
<SearchResult key={userlist.id} {...userlist} />
)))
let mapSearchedOnce = this.props.searchedOnce
return (
<div>
<FadeIn duration="300ms">
<div className="mid_rig_inner">
<div className="mid_inner">
<ul>
{ mapSearchedOnce
? map_usersList
: <SearchNoResult/>
}
{
mapSearchedOnce ?
(mapPageNo * 2 >= 3)
?
<div className="text-center my3 text-danger">
No more profiles. Try to modify search criteria.
</div> :
<div className="text-center my3">
<button type="button" className="btn btn-primary" onClick={this.loadMoreClick.bind(this)}>
Load More
</button>
</div>
: ''
}
</ul>
</div>
<div className="rig_inner">
<div className="my-4">
<div className="recomm">
<div className="recomm_top">
<span>Search</span>
</div>
</div>
<div className="search_advan_box">
<form onSubmit={this.handleSubmit.bind(this)}>
<select
name="religion"
className="mb-2"
value={this.props.formValues.religion}
onChange={this.handleChange.bind(this)}
>
<option value="" disabled="">
Select Religion
</option>
<option value="Any">Any Religion</option>
<option>Christian</option>
<option>Hindu</option>
<option>Muslim</option>
<option>Jain</option>
<option>Buddhist</option>
<option>Sikh</option>
<option>Parsi</option>
<option>Jewish</option>
<option>Spiritual</option>
<option>No Religion</option>
<option>Other</option>
</select>
<select
name="gender"
className="mb-2"
value={this.props.formValues.gender}
onChange={this.handleChange.bind(this)}
>
<option value="" disabled="">
Select Gender
</option>
<option>Male</option>
<option>Female</option>
<option>Other</option>
</select>
<input
type="submit"
className="my-4 btn btn-primary p2"
value={mapSearchedOnce ? "Refine Results":"Search Profiles"}
/>
</form>
</div>
</div>
</div>
</div>
</FadeIn>
</div>
)
}
}
const mapStateToProps = state => ({
users: state.Result.users,
searchedOnce: state.Result.searchedOnce,
pageNo: state.Result.pageNo,
formValues: state.Result.formValues
})
const mapDispatchToProps = {
getSearchResults,
setSearchedOnce,
setPageNum,
setFormValues
}
export default connect(mapStateToProps, mapDispatchToProps)(SearchAdvanced)
答案 0 :(得分:2)
当我更改选择时状态不会更新
这是因为您没有在handleChange
方法中调度Redux操作,而仅在handleSubmit
方法中调度了。只需在handleChange
中调度适当的操作即可解决此问题。
当我离开页面时,不会保留上次存储的状态
这是因为以前的值(在您离开之前)将仅保存在Redux存储中,而表单字段是从SearchAdvanced
组件的本地状态填充的。
要很好地解决这一问题,您应该完全摆脱本地状态。只能使用Redux存储。保持完整无缺是不必要的,并打破了Redux的“单一真相”。我建议您取消本地状态,只更新Redux状态,然后将值从Redux存储(组件的props
)传递到表单输入。
关于您尝试过此操作但遇到错误的记录:您需要更改以下内容:
<input value={ this.state.formValues.someValue }/>
到
<input value={ this.props.formValues.someValue }/>
其中formValues
来自Redux存储。
更新
现在是问题所在
this.props.setFormValues(this.props.formValues)
在handleChange
中。您正在使用旧的formValues进行更新,因此商店实际上从未进行过更新。我想你想要类似的东西:
handleChange(event) {
event.preventDefault();
const { name, value, type, checked } = event.target;
this.props.setFormValues({
...this.props.formValues,
[name]: type === 'checkbox' ? checked : value
});
}
这样您就可以使用用户的输入来更新商店的formValues
。复选框输入必须使用三元运算符,因为选中的复选框的value
是'on'
而不是true
,但是如果选中checked
属性是true
。
额外
似乎您是通过父级的道具将调度方法传递给SearchAdvanced
的。您可以(并且应该)通过使用connect
的第二个参数mapDispatchToProps
来做到这一点。这是一个示例:
const mapDispatchToProps = {
getSearchResults,
setSearchedOnce,
setPageNum,
setFormValues
}
export default connect(mapStateToProps, mapDispatchToProps)(SearchAdvanced);
然后,您可以将这些方法中的任何一个作为已绑定了派遣的方法来调用。所以
this.props.dispatch(setSearchedOnce(true))
成为
this.props.setSearchedOnce(true)
,您可以从父组件中删除调度的传递。