Reactjs 在handleSubmit中设置状态

Reactjs 在handleSubmit中设置状态,reactjs,single-page-application,jsx,setstate,Reactjs,Single Page Application,Jsx,Setstate,我有下面的handleSubmit()函数,它被称为表单的onSubmit: handleSubmit = (e) => { e.preventDefault() console.log(JSON.stringify(this.state)) if(this.validateForm()) this.props.history.push("/work?mins="+this.state.minutes+"&interest="+this.i

我有下面的
handleSubmit()
函数,它被称为表单的
onSubmit

handleSubmit = (e) => {
    e.preventDefault()

    console.log(JSON.stringify(this.state))
    if(this.validateForm())
        this.props.history.push("/work?mins="+this.state.minutes+"&interest="+this.interestsInitials())
    // the following line breaks everyhting
    this.setState({...this.state, pressedEnter: true})
}
validateForm
是另一个尝试更改状态的函数:

handleChanges = (e, changeName) => {
    switch (changeName) {
        case "minutes": 
            this.setState({...this.state, minutes: e.target.value})
            break
        case "business":
            this.setState({...this.state, interests:{...this.state.interests, business: e.target.checked} })
            break
        // ...
        default:
            console.log("Cannot identify the input")               
    }
}
我担心的是,调用
setState
彼此如此接近会破坏一切。这是真的吗

请注意,在以下标记中调用了
handleSubmit

<input type="checkbox" id="business" checked={ this.state.interests.business }
                       onChange={ (e) => this.handleChanges(e, "business") }/>
this.handleChanges(e,“business”)}/>

我不确定
这个.setState({…这个.state})
是否有效,应该有更好的选择:

// Only pass new changes
this.setState({ minutes: e.target.value });

// When things get a bit nested & messy
const interests = this.state.interests; // Might need to clone instead of direct assignment
interests.business = e.target.checked;
this.setState({ interests });
您还可以将回调传递给setState,如下所示:

this.setState({ minutes: e.target.value }, () => {
  // this callback is called when this setState is completed and the component is re-rendered
  // do more calculations here & safely set the new state changes
  const newState = { minutes: 12 };
  this.setState(newState);
});
function(newState) {
  newState.pressedEnter = true;
  // Make sure "this" is referring to the component though
  this.setState(newState);
};
为了避免如此紧密地调用设置状态,您可以让
validateForm
以对象的形式返回状态更改,将
按edeter:true
扩展到它,然后为所有更改调用最后一个设置状态,或者只使用如下回调:

handleChanges = (e, changeName, cb) => {
  const newState = this.state; // Might need to clone instead of direct assignment
  switch (changeName) {
    case "minutes": 
        newState.minutes = e.target.value; break;
    case "business":
        newState.interests.business = e.target.checked; break;
    //...
    default:
        console.log("Cannot identify the input"); break;           
  }
  cb(newState);
}
cb
可以是这样的:

this.setState({ minutes: e.target.value }, () => {
  // this callback is called when this setState is completed and the component is re-rendered
  // do more calculations here & safely set the new state changes
  const newState = { minutes: 12 };
  this.setState(newState);
});
function(newState) {
  newState.pressedEnter = true;
  // Make sure "this" is referring to the component though
  this.setState(newState);
};

如果事情变得太混乱,只需将上述回调转换为组件的方法。

您能提供错误信息吗?另外,您能否显示如何/在何处调用
handleSubmit
方法?输入变得无响应,它们不再改变状态。我在控制台中没有收到任何错误。我将在我的问题中添加调用函数的标记。嗯,我有点不确定这里的上下文。您是否可以提供一个重新创建问题的小提琴示例?在调用
this.setState
时,您不需要展开
…this.state
。如果将对象作为第一个参数传递给
setState
,它将执行与当前状态的浅合并。我认为这不会显著影响性能。谢谢,它很有效。更新嵌套对象时,如何避免在不创建临时变量(例如
this.setState({interests:{…this.state.interests,design:e.target.checked}},this.checkErrorsAgain)的情况下使用spread运算符
如果您要查找的是一行代码,那么这可能也会起作用:
this.setState(prevState=>({interests:Object.assign(prevState.interests,{design:e.target.checked}),callback);
但是使用一个临时变量总是更容易阅读和以后更改,我想:
const interests=this.state.interests;interests.design=e.target.checked;this.setState({interests},callback)
记住从上一个状态克隆对象,而不是使用直接赋值。我不知道您在使用什么库,所以我省略了这一部分,以使代码更清晰。您可以使用lodash执行类似于
const interests=.cloneDeep(this.state.interests);
的操作,甚至可以对React组件的状态使用immutable(我的建议!)。好的,但是使用
对象没有任何好处。分配
与扩展运算符,因此我认为我将坚持使用扩展运算符。是的,可能应该坚持使用您可以读得更快和更喜欢的内容:)