反应 16.3+ 正确的触发方式从状态更改



所以我有这个组件:

import React from 'react';
import PropTypes from 'prop-types';
import { isEqual } from 'lodash';
class SomeComponent extends React.Component {
static propTypes = {
onChange: PropTypes.func,
};
previousItems = [];
constructor(props) {
super(props);
this.state = {
items: ['some', 'list'],
};
}
setState(stateSetter) {
super.setState(previousState => {
const newState = stateSetter(previousState);
if (!isEqual(newState.items, this.previousItems)) {
this.props.onChange && this.props.onChange(newState.items);
this.previousItems = newState.items;
}
return newState;
});
}
}

我试图做的是监听状态的变化,并在状态改变时触发onChange。我曾经使用componentWillUpdate来做到这一点,但我听说这在 React 17 中会改变。

现在正确的方法是什么?我上面所做的感觉很笨拙。

谢谢!

查看 componentDidUpdate(( 的文档

这是副作用应该发生的地方,就像 ajax 调用或在这种情况下调用 onChange 一样,但你必须检查 props 是否真的发生了变化(就像你在代码中所做的那样(。

请注意,此方法不会在初始呈现中调用,只会在下次更新时调用。非常适合 onChange 活动。

请注意,如果 onChange 方法设置了状态,它可以启动一个无限循环(fire onChange -> set state -> fire onChange -> ....(。如有必要,请检查更改的状态/道具,并仅在必要时触发 onChange 事件(避免无限循环(。

为了澄清问题,这里是即将到来的 React 更新路径的简短描述。弃用警告将在下一个次要 React 更新中推出,因此最早在 16.4 中推出,但弃用的方法将一直有效,直到下一个主要版本 17 更新。

我不建议在生命周期方法中componentDidUpdatesetState,因为它会使您非常容易受到循环的影响。

我不太确定您通过检查您的state是否已更改并且状态更改应始终由用户操作引起来尝试实现什么。当您调用 setState 时,您的组件将自动重新呈现。

为了澄清问题,我自己会做这样的事情。你根据用户操作进行状态更改,当你调用 setState 时,你的 React-components 将始终重新渲染。这是反应性质。

如果我想传递数据,我会声明子组件并将数据作为 props 传递。然后使用 React 16.3 中新引入的子组件状态示例将其传递给子组件状态示例getDerivedStateFromProps该方法返回普通对象并自动传递给组件状态。此方法在初始渲染时调用,每次组件接收新 props 时都会调用,因此基本上每次父组件状态更改时,在这种情况下。

如果您不希望子组件重新呈现,也可以从getDerivedStateFromProps-方法return null

class MyComponent extends React.Component {
// ES7 syntax, same as doing this in constructor
// with, this.state = {}
state = {
value: false
}
handleClick = () => {
/* Might as well write some logic here
* and do setState at end
*/
const { value } = this.state        
/* and at end, well I just return value negated back */
this.setState({
value: !value
})
}
render() {
const { value } = this.state
return (
<div>
{value ? 'im true' : 'im falsy'}
<button onClick={this.handleClick} >Click me!</button>
<SomeOtherComponent {...this.state} />
</div>
)
}
}

class SomeOtherComponent extends React.Component {
static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.value) {
return { text: 'it was true ' }
}
return { text: 'it was falsy' }
}
state = {
text: null,
}
render() {
return (
<div>
{ this.state.text }
</div>
)
}
}

最新更新