【问题标题】:Why react component can re-render when redux reducer do not return a new array?当redux reducer不返回新数组时,为什么react组件可以重新渲染?
【发布时间】:2021-10-02 14:22:14
【问题描述】:

我们知道,如果我们想重新渲染一个由 react-redux 连接的 react 组件,我们应该在派发相关动作时在 reducer 中返回一个新数组。我的问题是,为什么当 redux reducer 不返回新数组时,react 组件可以重新渲染? 当我点击应用组件按钮时,第一个应用名称变成'aaa',为什么???

行动:

export function setAppName(name: string) {
  return {
    type: 'SET_APP_NAME',
    name,
  }
}

减速器:

export function appInfos(state = {
  appInfos: [
    {name: 'ccc'},
    {name: 'ddd'},
  ]
}, action: any) {
  switch(action.type) {
    case 'SET_APP_NAME':
      // just return origin array, not a new array
      const appInfos = state.appInfos;
      appInfos[0].name = action.name
      return Object.assign({}, state, { appInfos })
    default:
      return state;
  }
}

组件应用:

function mapStateToProps(state: any) {
  return {
    app: state.appInfos
  }
}

function App() {
  const { app } = useSelector(mapStateToProps)
  const dispatch = useDispatch()
  const onClick = useCallback(() => {
    dispatch(setAppName('aaa'))
  }, [dispatch])

  return (
    <div className="app">
      {app.appInfos.map((info: any) => {
        return <div key={info.name}>{info.name}</div>
      })}
      <button onClick={onClick}>click</button>
    </div>
  );
}

容器和存储:

const store = createStore(combineReducers({
  appInfos
}))

ReactDOM.render(
  <Provider store={store}>
    <React.StrictMode>
    <App />
  </React.StrictMode>
  </Provider>,
  document.getElementById('root')
);

【问题讨论】:

标签: reactjs redux react-redux


【解决方案1】:

您混淆了connectuseSelector 的使用,这会导致不必要的渲染。

connect 接受mapStateToProps 函数作为参数,必须返回一个对象,因为所有字段都将成为组件的新道具。如果任何单个字段更改为新引用,该组件将重新呈现:

https://react-redux.js.org/using-react-redux/connect-mapstate

然而,useSelector 接受一个必须返回 one 值的选择器函数,并且如果该 one 引用更改为新值,它将重新呈现:

https://react-redux.js.org/api/hooks#equality-comparisons-and-updates

现在,您正在编写一个总是返回一个新对象引用的函数。您的函数将始终每个分派的动作之后运行,因此它将始终强制组件重新渲染。

将其更改为:

function selectAppInfo(state) {
  return state.appInfos
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-02-22
    • 2018-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 2023-02-20
    • 2017-06-17
    相关资源
    最近更新 更多