在React中解构state/props

9

我正在学习React,并且在我的项目中安装了Eslint。它开始给我报错,例如:

Use callback in setState when referencing the previous state. (react/no-access-state-in-setstate)
Must use destructuring state assignment (react/destructuring-assignment)

我尝试查找此问题,但无法正确理解。

有人能指导我正确方向吗?

这是我的代码,会抛出错误:

class LoginForm extends React.Component {
  state = {
    data: {
      email: "",
      password: "",
    },
    loading: false,
    errors: {},
  };

  onChange = e =>
    this.setState({
      data: { ...this.state.data, [e.target.name]: e.target.value },
    });

  onSubmit = () => {
    const errors = this.validate(this.state.data);
    this.setState({ errors });

    if (Object.keys(errors).length === 0) {
      this.setState({ loading: true });
      this.props
        .submit(this.state.data)
        .catch(err =>
          this.setState({
            errors: err.response.data.errors,
            loading: false,
          }),
        );
    }
  };
}

据我理解,我需要解构this.statethis.props,但如何实现呢?
编辑:根据下面的建议,我最终得到了这个结果。现在我需要解决的问题只有props了。它要求我使用析构props赋值。
onChange = ({ target: { name, value } }) =>
    this.setState(prevState => ({
        data: { ...prevState.data, [name]: value }
    }));

onSubmit = () => {
    const { data } = this.state;
    const errors = this.validate(data);
    this.setState({ errors });

    if (Object.keys(errors).length === 0) {
        this.setState({ loading: true });
        this.props
            .submit(data)
            .catch(err =>
                this.setState({ errors: err.response.data.errors, loading: false })
            );
    }
};

提前感谢您,对于这个新手问题我们表示歉意。


6
setState 是异步的。所以如果你调用 setState 并使用之前的状态,可能会使用错误的状态!因此,请使用回调函数获取之前的状态,并以安全的方式使用它。 这个链接可能会有所帮助:https://medium.com/@voonminghann/when-to-use-callback-function-of-setstate-in-react-37fff67e5a6c。 - Maor Refaeli
谢谢! 我会查看的。 - dragi
嘿,Redux 中的 ...state 是什么意思?如何在 Redux 中进行解构操作? - Prashanth Yarram
我使用了这个解决方案 https://dev59.com/zq7la4cB1Zd3GeqPiL65#52565081 并且它在我的情况下正常工作。 - Salma Gomaa
3个回答

23

当 eslint 抛出 react/destructuring-assignments 错误时,它想告诉您的是这样的赋值方式:

const data = this.state.data;

可以改写为:

const { data } = this.state;

这也适用于函数参数,因此:

onChange = e => { ... }

可以写成

onChange = ({target: {value, name}}) => { ... }

react/no-access-state-in-setstate 的下一个错误告诉您正在编写:

this.setState({
    data: { ...this.state.data, [e.target.name]: e.target.value }
});

当你本应该写作时:

this.setState(prevState => ({
    data: { ...prevState.data, [e.target.name]: e.target.value }
}));

或者,如果您将其与react/destructuring-assignments规则相结合:

onChange = ({target: {name, value}}) =>
    this.setState(prevState => ({
        data: { ...prevState.data, [name]: value }
    }));

您可以在此处阅读有关这两个规则的更多信息:

react/destructuring-assignment

react/no-access-state-in-setstate


1
第二种方法会报错,请查看此答案以获取更多详细信息:链接 - Mayank Shukla
1
这对我有用,我编辑了我的原始帖子并提出了新问题。 现在我的状态很好。我只需要编辑道具,但它比上面的示例要复杂一些。 - dragi
1
在这种情况下,您可以只写:const {submit} = this.props; 然后调用 submit(data).catch(...) - Joliver
太棒了。现在有点明白了。 - dragi

5

解构赋值基本上是语法糖。一些 Eslint 配置更喜欢使用它(我猜这就是你的情况)。

它基本上是声明值并将其与不想重复的语法位相等,例如给定 React props:

this.props.house, this.props.dog, this.props.car

解构 --->

 const { house, dog, car } = this.props;

现在你可以使用house、dog或任何你想要的东西。它通常与React中的state和props一起使用,以下是更多相关文档,希望对你有所帮助。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment


0

这是你的 onChange 方法出现了问题。尝试使用以下代码:

onChange = e =>
    this.setState(prevState => ({
        data: { ...prevState.data, [e.target.name]: e.target.value }
    }));

请查看来自https://reactjs.org/docs/state-and-lifecycle.html的“状态更新可能是异步的”部分。


它将抛出一个错误,请查看此答案以获取更多详细信息:https://dev59.com/3qTia4cB1Zd3GeqP7QVg#45483658。 - Mayank Shukla

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接