首页 > 解决方案 > Redux:更改存储中的值不会触发我使用相同值的另一个组件

问题描述

我尝试了其他类似的建议,但没有任何效果,因此我发布了我自己的问题。所以我有一个使用 redux 的 react js 应用程序。我需要显示一个列下拉列表,我可以使用它来设置表的列以显示或隐藏。我有一个标题组件和一个列表组件,它们都是兄弟姐妹。我正在尝试更改标题组件中 columnList 的值,调度更新操作以在存储中更新,并在此基础上尝试更改列表组件中的列。我目前的问题是,当我更改 columnList 的可见性时,我的列表组件没有重新呈现,也没有触发 useEffect。但是,让我更困惑的是,在打开 chrome 中的检查时,一旦我更改了标题组件中的 columnList 值,

下面是列表组件,不相关的部分和附加的列列表值没有被包括在内

const columnList=useSelector(selectColumnList,shallowEqual);

var columns = [
    {
      id:1,
      title: "RPA ID",
      dataIndex: "",
      columnVisible:true,
      render: (record) => {
        let id = record.id.toString().padStart(3, "0");
        return `RPA${id}`;
      },
    },]

  useEffect(()=>{
    console.log("triggering dispatch")
    dispatch(updateOpportunityColumns(columns));
  },[])

const renderBody = (props, columns) => {
      return (
        <tr className={props.className}>
          {columns.map((item, idx) => {
            if (item.columnVisible) {
              return props.children[idx]
            }
          })}
        </tr>
      );
    }

    const renderHeader = (props, columns) => {
      return (
        <tr>
          {columns.map((item, idx) => {
            if (item.columnVisible)
              return props.children[idx];
          })}
        </tr>
      );
    }

  return (
    <div>
      <Table
        rowKey="uid"
        onRow={(record, rowIndex) => {
          return {
            onDoubleClick: () => {
              history.push({
                pathname: `${
                  RouteNames.Opportunity.path
                }/RPA${record.id.toString().padStart(3, "0")}`,
                opportunityId: record.id,
              });
            },
          };
        }}
        columns={columnList}
        dataSource={pagedData}
        pagination={{
          total: total,
          defaultPageSize: pageSize,
          current: currentPage,
          onChange: onPageChange,
        }}
        components={{
          header: {
            row: (props) => renderHeader(props, columnList),
          },
          body: {
            row: (props) => renderBody(props, columnList)
          },
        }}
      />
    </div>
  );
};

下面是我的标题

var columns=useSelector(selectColumnListIntermediate,shallowEqual)
const [state,setState]=useState();

  function handleDropdownCheckboxClick(i,event){
    event.stopPropagation();
    dispatch(updateOpportunityColumnAtIndex(i));
  }

const menus=Object.entries(columns).map((key,i)=>{
    if(key[1].title){
      return(
        <Menu key={key[0]}>
        <Menu.Item key={key[0]}>
          <Checkbox checked={key[1].columnVisible} onClick={(e)=>{handleDropdownCheckboxClick(i,e)}} >{key[1].title}</Checkbox>
        </Menu.Item>
      </Menu>
  )}})

  const menu = () => {
    return (
      <Menu onClick={""}>
        {menus}
      </Menu>
    )};
  return (
    <div>
      <div style={{ display: "flex", alignItems: "flex-end" }}>
        <Avatar
          style={{ marginRight: "5px" }}
          shape="square"
          size={64}
          src={`${URL}${logoUrl}`}
        />

        <Title style={{ color: "#0AA9F0" }} level={3}>
          {name}
        </Title>
      </div>
      <Divider />

      <div>
        <Button
          className="btn-border"
          onClick={handleClick}
          style={{ width: "300px" }}
          type="primary"
          shape="circle"
          icon={<PlusOutlined />}
        >
          Create Opportunity
        </Button>
        
        
        <Dropdown.Button overlay={menu}>
          Columns
        </Dropdown.Button>

        <div className="userlist">
          <Search
            placeholder="Search"
            allowClear
            onSearch={(value) => onSearch(value)}
            enterButton
          />
        </div>
      </div>
    </div>
  );
};

最后下面是我的减速器

case UPDATE_COLUMNS_LIST:
{
       return {
        ...state,
        ColumnListIntermediate:payload,
        ColumnList:payload,
      };}

case UPDATE_COLUMN_LIST_AT_INDEX:{
        const newArray = [...state.ColumnList];
        newArray[action.payload].columnVisible = !state.ColumnList[payload].columnVisible
        return { 
          ...state,
          ColumnList:newArray,
          ColumnListIntermediate:newArray,
         }
      };

和行动文件

export const getOpportunityColumns = () => ({
  type: GET_COLUMNS_LIST
});

export const getOpportunityColumnsIntermediate = () => ({
  type: GET_COLUMNS_LIST_INTERMEDIATE
});

export const updateOpportunityColumns = (ColumnValue) => ({
  type: UPDATE_COLUMNS_LIST,
  payload: ColumnValue,
});

export const updateOpportunityColumnAtIndex = (index) => ({
  type: UPDATE_COLUMN_LIST_AT_INDEX,
  payload: index,
});

抱歉,文件太大,包含要完全发布的其他内容。

标签: reactjsreduxredux-saga

解决方案


您几乎就在那里,但仍在变异,您应该仔细阅读并尝试了解如何以不可变的方式进行更新

这是应该工作的代码:

case UPDATE_COLUMN_LIST_AT_INDEX: {
  //map state.ColumList to new array
  const newArray = state.ColumnList.map((item, index) =>
    index === action.payload
      ? //toggle columVisible if index is action payload
        { ...item, columnVisible: !item.columnVisible }
      : //return item unchanged, index is not action.payload
        item
  );
  return {
    ...state,
    ColumnList: newArray,
    ColumnListIntermediate: newArray,
  };
}

如果这不起作用,您应该检查正在渲染的内容我不知道 Table 组件是什么,但是当道具更改时它可能不会重新渲染,因为它有一个错误的实现,我知道旧的 react bootstrap 有一些问题。


推荐阅读