簡體   English   中英

State 用作組件中的道具,state 更改不會重新渲染組件

[英]State use as props in component, state change will not re-render the component

如果 state 更改,React 將重新渲染。 那么為什么下面的情況不能重新渲染呢?

根據程序行為,我發現

  1. 當 state 發生變化時,如果 state 在組件中直接使用,則會重新渲染。
  2. 當 state 發生變化時,如果 state 在子組件中用作道具,則不會重新渲染。
  3. 如何直接重新渲染該子組件?

以下程序來自我的代碼並進行了一些修改。 更新:箱這是我在沙箱中創建的代碼,我嘗試模擬我的真實情況

function List(props) {

    const [fullListValue, setFullListValue] = useState([]); //store data which get from server
    const [dropDrowList, setDropDrowList] = useState([]); //store data column value (e.g. data contain "fruit" column, this state will store "apple", "berry", "banana" etc.)

    const setAllList = (data) => {
        setFullListValue(data);
    };
    useEffect ( ()=> {
      //axios call server, use setAllList(data) to save state
    ,[]}

    //when fullListValue is updated, 
    useEffect(() => {
        const dropDrowListCopy = [{ ['label']: 'ALL', ['value']: 'ALL' }];
        //push all "fruit" data in dropDrowListCopy without duplicate
        console.log(dropDrowListCopy); //this will show all dropdown I want, i.e. "ALL","apple", "berry", "banana"
        setDropDrowList(dropDrowListCopy); //set to dropDrowList, and I expect this step will re-render the SelectionList component, however, it do not
    }, [fullListValue]);

    return (
        <div>
            <div>
                {dropDrowList.length <= 1 ? (
                    'loading'  //I add this to re-render the component, but I think this is not a good way to re-render the component
                ) : ( 
                    <SelectionList
                        itemList={dropDrowList}
                    />
                )}
            </div>
        </div>
    );
}

您需要更改此條件:

dropDrowList.length <= 1

您僅將 1 object 分配給 dropDrowList,因此它不會呈現 SelectionList。

更改為:

dropDrowList.length < 1

應該啟用 SelectionList 來呈現。

問題

SecitonList中,您將傳遞的道具存儲到 state 但不會在道具更改時更新 state,從而留下陳舊的 state。 出於這個原因,將 props 存儲在本地組件 state 實際上是一種 React 反模式。

解決方案

道具更改時更新 state。

function SelectionList(props) {
  const [listItem, setListItem] = useState(
    props.itemList ? props.itemList : []
  );

  useEffect(() => {
    setListItem(props.itemList);
  },
  [props.itemList]);

  return (
    <FormControl>
      <Select
        renderValue={
          props.multiple ? (selected) => fieldDisplay(selected) : null
        }
        input={<Input />}
      >
        {listItem.map((item) => (
          <MenuItem key={item.value} value={item}>
            {props.multiple ? (
              <Checkbox checked={selectedValue.indexOf(item) > -1} />
            ) : null}
            <ListItemText primary={item.label} />
          </MenuItem>
        ))}
      </Select>
    </FormControl>
  );
}

解決方案——直接消耗道具

function SelectionList(props) {
  return (
    <FormControl>
      <Select
        renderValue={
          props.multiple ? (selected) => fieldDisplay(selected) : null
        }
        input={<Input />}
      >
        {props.itemList.map((item) => (
          <MenuItem key={item.value} value={item}>
            {props.multiple ? (
              <Checkbox checked={selectedValue.indexOf(item) > -1} />
            ) : null}
            <ListItemText primary={item.label} />
          </MenuItem>
        ))}
      </Select>
    </FormControl>
  );
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM