繁体   English   中英

React Redux-如何存储表单状态,以便当用户返回页面时可以再次填充它

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM