【问题标题】:unintentional state update in react form反应形式的无意状态更新
【发布时间】:2017-09-30 17:32:18
【问题描述】:

首先这是一个简化的例子:Codepen Project

我正在 react 中构建一个编辑表单,用于检查是否有任何更改。 如果有任何更改,您只能保存表单,并且您所做的任何更改都将通过更改匹配输入元素的样式(左边框)来显示。 It looks like this

为此,我将原始数据/状态保存在 componentDidMount 方法中的组件状态中,并将其与不同输入的状态进行比较。

componentDidMount() {
// if the project is accessed from home and is not a new project, project data will be passed along
if (this.props.project) {
  this.setState({
    name: this.props.project.name,
    tags: this.props.project.tags
  }, this.setInitialState)
} else if (this.props.edit && this.props.match.params.id) {
  // instead of an api call to get project data, if the project is accessed directly by url
  const project = projects.find((project) => project.name === this.props.match.params.id)
  this.setState({
    name: project.name,
    tags: project.tags
  }, this.setInitialState)

}
// if there are no project data or an edit prop, it's a new project and the initialState remains empty
}

在每次输入更改时,输入值都会与初始状态进行比较:

compareInputData() {
const formFields = {
  name: {
    ref     : this.name,
    changed : false
  },
  tags: {
    ref     : this.tagList,
    changed : false
  }
}

const state = this.state
const first = this.state.initialState

const nameHasChanged  = state.name        !== first.name
const tagsHaveChanged = state.tags.length !== first.tags.length

nameHasChanged
  ? ( formFields.name.changed = true )
  : ( formFields.name.changed = false )

tagsHaveChanged
  ? ( formFields.tags.changed = true )
  : ( formFields.tags.changed = false )

nameHasChanged || tagsHaveChanged
  ? (this.setState({
      isChanged: true
    }))
  : (this.setState({
      isChanged: false
    }))

this.handleChangedInputStyles(formFields)
  }

如果有改变匹配元素的样式改变:

handleChangedInputStyles(formFields) {
const formFieldKeys = Object.keys(formFields)

formFieldKeys.map(key => {
  formFields[key].changed
    ? formFields[key].ref.style.borderLeft = `2px solid orange`
    : formFields[key].ref.style.borderLeft = '1px solid black'
})

}

这在正常输入字段上按我想要的方式工作,但我还将相关标签保存为数组,显示为列表。 每当我更新该列表 (this.state.tags) 时,我的标签原始状态也会更新 (this.state.initialState.tags),这意味着我无法在我的标签列表中获取更改。 但是,如果我正在向新项目添加标签而不是编辑现有项目,它确实有效...... 我不知道如何解决这个问题,因为我真的不知道是什么原因造成的,我希望得到一些帮助。

感谢您阅读这篇文章:)

【问题讨论】:

    标签: javascript forms reactjs


    【解决方案1】:

    不要在状态中存储this.state.initialState。而是将其存储在成员中。例如:

    constructor(props) {
      this.initialState = Object.assign({}, whatever...);
      this.initialState.tags = [].concat(this.initialState.tags); // Keep a shallow copy of this array.
    }
    

    注意:在内部,React 可能会修改 tags 数组。如果您保留一份副本,该副本将不会被修改。

    【讨论】:

    • 很好,只要我包含第二行,它实际上就可以工作。如果我不这样做,this.initialState 也将被更新。不幸的是,我仍然不明白为什么会发生这种情况,或者为什么第二行会阻止这种情况......
    • @YannickPanis 检查注释。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-26
    • 2022-01-23
    • 2018-03-28
    • 1970-01-01
    • 2021-07-26
    相关资源
    最近更新 更多