我有一个带有prop的react组件,该组件通过redux connect方法传递。有一个useEffect专门链接到该道具,该道具应该在更改时执行异步调用。问题是,无论我在道具上附加了useEffect而不更改,只要我在该应用中的其他任何地方更改redux状态,都会触发useEffect。
useEffect方法看起来像这样
useEffect(() => {
if (userPhoneNumber) {
myAsyncFunction()
.then(() => {
showData()
})
}
}, [userPhoneNumber])
和userPhoneNumber道具通过react-redux connect
方法传递,如下所示:
const mapStateToProps = state => {
return {
userPhoneNumber: state.appState.userPhoneNumber
}
}
export default connect(mapStateToProps)(MyComponent)
据我了解,这可能会在两个潜在的地方打破。一方面,如果userPhoneNumber
属性不变,则useEffect不应该被触发。另外,mapStateToProps方法不会返回新值,因此它不应触发任何形式的重新渲染。
导致意外的useEffect调用的redux状态更改来自具有与此组件相似的react-redux connect设置的兄弟组件,而prop映射的状态不同。
当reducer运行时,您将拥有一个全新的状态对象,因此有了一个新的userPhoneNumber
prop参考。您应该记住userPhoneNumber
值。我使用reselect创建记忆状态选择器,但您可能可以使用useMemo
钩子,并在效果的依赖项中使用that记忆值。
const memoizedUserPhoneNumber = useMemo(() => userPhoneNumber, [userPhoneNumber]);
useEffect(() => {
if (memoizedUserPhoneNumber) {
myAsyncFunction()
.then(() => {
showData()
})
}
}, [memoizedUserPhoneNumber]);
使用重新选择
import { createSelector } from 'reselect';
const appState = state => state.appState || {};
const userPhoneNumber = createSelector(
appState,
appState => appState.userPhoneNumber;
);
...
const mapStateToProps = state => {
return {
userPhoneNumber: userPhoneNumber(state),
}
}
尽管这些都没有阻止父母重新渲染整个功能组件,所以要解决此问题,您需要使用memo
HOC帮助“记忆”馈入组件的道具。
memo