使用 redux 和 createSelector 时 React 组件不会更新,无法检测 UI 变化

问题描述 投票:0回答:1

我在不可变的 redux 状态下创建了组中的用户选择器:

import { useStore } from 'react-redux';
import { createSelector } from '@reduxjs/toolkit'

const selectGroup = (state) => state.group;

const memoizedUsers = createSelector([selectGroup], (group) => {
    return group.get('users').toJS();
})

const useMemoizedUsers = () => {
    const store = useStore();
    return memoizedUsers(store.getState());
}

然后在我的组件中显示用户列表,并提供删除用户的选项:

const DeleteButton = ({ rowIndex )} => {
    const dispatch = useDispatch();
    return (
     <Button onClick={() => {
        dispatch({
          type: '@@group/removeUser',
          payload: { rowIndex }
        })
      }}>
       Delete
     </Button
    )
}

const columnDefs = [
    {
      headerName: 'Name',
      field: 'name',
    },
    {
      headerName: 'Age',
      field: 'age',
    },
    {
      headerName: '',
      field: 'onDelete',
      cellRenderer: ({ node: { rowIndex } )} => {
        return (
          <DeleteButton rowIndex={rowIndex} />
        )
      }
    }
];

const UserList = () => {
    const users = useMemoizedUsers();

    return {
        <Grid 
          rowData={users}
          columnDefs={columnDefs}
        />
    }
}

当我点击删除时,我看到 redux 存储正在更新 ==> 从 10 个用户减少到 9 个用户。 但是,我的 UserList 组件没有重新渲染,UI 仍然显示所有 10 个用户。

有人知道如何强制更新组件还是我错误地使用了createSelector?

如果我更改 const 用户:

const users = useSelector((state) =>
  state.group.get('users')?.toJS()
}

组件重新渲染并且用户列表更新,但我收到 redux 警告,当使用相同的参数调用时,Selectorknown 返回了不同的结果。这可能会导致不必要的重新渲染。

此外,我可以像这样重写 UserList:

const UserList = () => {
    const users = useSelector((state) =>
      state.group.get('users')
    }

    return {
        <Grid 
          rowData={users.toJS()}
          columnDefs={columnDefs}
        />
    }
}

以这种方式编写组件会重新渲染 UI,并且 redux 警告会消失,但这违背了使用 createSelectors 的目的

javascript reactjs redux immutable.js
1个回答
0
投票

useStore
挂钩实际上并不订阅商店的更新。
store.getState
基本上是一个一次性的函数调用,它从存储中获取并返回当前状态值一次。

const useMemoizedUsers = () => {
  const store = useStore();
  return memoizedUsers(store.getState()); // <-- doesn't subscribe to store changes
}

createSelector
实际上已经创建了一个记忆选择器函数,因此您只需在
useSelector
钩子调用中直接使用它即可。

const selectGroup = (state) => state.group;

const selectGroupUsers = createSelector(
  [selectGroup],
  (group) => group.get('users').toJS()
)
import { useSelector } from 'react-redux';

...

const UserList = () => {
  const users = useSelectors(selectGroupUsers);

  return {
    <Grid 
      rowData={users}
      columnDefs={columnDefs}
    />
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.