gpt4 book ai didi

reactjs - React 不会在数组状态更新时重新渲染

转载 作者:行者123 更新时间:2023-12-05 08:37:38 25 4
gpt4 key购买 nike

我正在尝试制作 3 个按钮控件来打开和关闭 3 个相应的菜单列表。 Material-UI 是我目前使用的 UI 框架。这是代码:


const Filters = () => {

const [anchors, setAnchors] = useState([null, null, null])

const handleClick = (event, index) => {
const arr = anchors
arr[index] = event.target
setAnchors(arr)
}

const handleClose = (index) => {
const arr = anchors
arr[index] = null
setAnchors(arr)
}

return(
<div id="top-filters">
<div className="controls">
<Button onClick={(event) => handleClick(event, 0)}>Sort By</Button>
<Button onClick={(event) => handleClick(event, 1)}>Price</Button>
<Button onClick={(event) => handleClick(event, 2)}>Delivery Fees</Button>
</div>
{
console.log({anchors})
}
<Menu key={1}
anchorEl={anchors[0]}
open={Boolean(anchors[0])}
onClose={() => handleClose(0)}
keepMounted
>
<MenuItem>
<ListItemText primary="By Rating" />
</MenuItem>
</Menu>

<Menu key={2}
anchorEl={anchors[1]}
open={Boolean(anchors[1])}
onClose={() => handleClose(1)}
keepMounted
>
<MenuItem>
<Slider defaultValue={25} marks={marks} step={25} />
</MenuItem>
</Menu>

<Menu key={3}
anchorEl={anchors[2]}
open={Boolean(anchors[2])}
onClose={() => handleClose(2)}
keepMounted
>
<MenuItem>
<ListItemText primary="By Delivery Fees" />
</MenuItem>
</Menu>

<FormControl className="search-bar-filter">
<Icon>search</Icon>
<StyledInput classes={{ root: classes.root }} name="search" type="search" placeholder="Search" disableUnderline />
</FormControl>
</div>
)
}

export default Filters

我检查了控制台中的值更新,它们看起来不错,但我不确定为什么 React 不会重新呈现页面(当我单击按钮时,没有任何反应,但 anchor 状态已更新)。感谢您的帮助。

最佳答案

你正在做的是一个突变:

arr[index] = event.target

更新状态时应避免突变。因为如果你改变你的状态,React 无法理解你的状态已经改变。您可以使用 mapfilter 或任何其他不会改变您的状态的方法。

const handleClick = (event, index) => {
setAnchors((prev) =>
prev.map((el, i) => {
if (i !== index) {
return el;
}

return event.target;
})
);
};

或者如果你喜欢简洁的:

const handleClick = (event, index) => {
setAnchors((prev) => prev.map((el, i) => (i !== index ? el : event.target)));
};

展开语法可用于非嵌套数组,但如果您正在处理嵌套数组并更改嵌套值,请务必小心,因为展开语法会创建浅拷贝。这就是为什么我喜欢在大多数时候使用像 map 这样的方法。

如果你不想映射整个数组(有些人更喜欢这样)Object.assign 和 spread syntax 可以一起使用。

const handleClick = (event, index) => {
setAnchors((prev) => Object.assign([], { ...prev, [index]: event.target }));
};

更新:

正如我之前解释的那样,传播语法只会生成浅拷贝。

Note: Spread syntax effectively goes one level deep while copying anarray. Therefore, it may be unsuitable for copying multidimensionalarrays, as the following example shows. (The same is true withObject.assign() and spread syntax.)

Source

这意味着嵌套值与原始值保持相同的引用。因此,如果您为新数组(或对象)更改某些内容,它也会更改原始数组。

const arr = [
{ id: 0, name: "foo" },
{ id: 1, name: "bar" },
{ id: 2, name: "baz" },
];

const newArr = [...arr];

newArr[0].name = "something else";

console.log("newArr", newArr);
console.log("original arr", arr);

如您所见,我们的原始数组也发生了变化。实际上,这不是嵌套数组,但我们正在更改数组元素的嵌套属性。也许这是嵌套数组的更好示例,但上面的示例更现实。

const arr = [["foo", "bar"], [1,2]];

const newArr = [...arr];

newArr[0][0] = "fizz";

console.log(newArr);
console.log(arr);

关于reactjs - React 不会在数组状态更新时重新渲染,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64982593/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com