[英]React Redux - How to store form state so that it can be populated again when user returns to page
我有一个加载结果的搜索表单。 除了在表单字段中选择的值之外,所有内容都在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)
更改选择时状态不会更新
这是因为您没有在handleChange
方法中调度Redux动作,仅在handleSubmit
方法中调度了。 只需在handleChange
调度适当的操作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
来更干净地执行此mapDispatchToProps
。 这是一个例子:
const mapDispatchToProps = {
getSearchResults,
setSearchedOnce,
setPageNum,
setFormValues
}
export default connect(mapStateToProps, mapDispatchToProps)(SearchAdvanced);
然后,您可以将任何这些方法调用为已绑定了调度的方法。 所以
this.props.dispatch(setSearchedOnce(true))
变成
this.props.setSearchedOnce(true)
您可以从父组件中删除传递的传递。
connect
文档: https : //github.com/reduxjs/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.