React will re-render if the state is changed. Then why the following situation cannot be re-render?
Base on the program behavior, I found that
The following program is come from my code with some modification. Update: SandBox This is the code i created in sandbox, I have try to simulate my real situation
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>
);
}
In SecitonList
, you are storing passed props into state but not updating state when props change, leaving you with stale state. It's actually a React anti-pattern to store props in local component state for this reason.
Update state when props change.
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>
);
}