Jan*_*ong 6 reactjs material-ui react-hooks
我正在尝试制作 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
Run Code Online (Sandbox Code Playgroud)
我检查了控制台中的值更新,它们看起来很好,但我不确定为什么 React 不会重新渲染页面(当我单击按钮时,没有任何反应,但锚点状态已更新)。感谢帮助。
dev*_*kan 12
你正在做的事情是一个突变:
arr[index] = event.target
Run Code Online (Sandbox Code Playgroud)
更新状态时应该避免突变。因为如果你改变你的状态 React 就无法理解你的状态已经改变。您可以使用类似 的方法map,filter或任何其他不会改变您的状态的方法。
const handleClick = (event, index) => {
setAnchors((prev) =>
prev.map((el, i) => {
if (i !== index) {
return el;
}
return event.target;
})
);
};
Run Code Online (Sandbox Code Playgroud)
或者如果你喜欢简洁的:
const handleClick = (event, index) => {
setAnchors((prev) => prev.map((el, i) => (i !== index ? el : event.target)));
};
Run Code Online (Sandbox Code Playgroud)
扩展语法可用于非嵌套数组,但如果您正在处理嵌套数组并更改嵌套值,请务必小心,因为扩展语法会创建浅副本。map这就是为什么我大多数时候喜欢使用方法。
如果您不想映射整个数组(有些人更喜欢这样做)Object.assign和扩展语法可以一起使用。
const handleClick = (event, index) => {
setAnchors((prev) => Object.assign([], { ...prev, [index]: event.target }));
};
Run Code Online (Sandbox Code Playgroud)
更新:
正如我之前所解释的,扩展语法仅进行浅复制。
注意:复制数组时,扩展语法实际上会深入一层。因此,它可能不适合复制多维数组,如以下示例所示。(Object.assign() 和扩展语法也是如此。)
这意味着嵌套值保留与原始值相同的引用。因此,如果您更改新数组(或对象)的某些内容,它也会更改原始数组(或对象)。
arr[index] = event.target
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,我们的原始数组也发生了变化。实际上,这不是嵌套数组,但我们正在更改数组元素的嵌套属性。也许这是嵌套数组的一个更好的例子,但上面的例子更现实。
const handleClick = (event, index) => {
setAnchors((prev) =>
prev.map((el, i) => {
if (i !== index) {
return el;
}
return event.target;
})
);
};
Run Code Online (Sandbox Code Playgroud)
您错误地更新了状态。
const arr = anchors不是克隆锚点的正确方法。您需要使用...运算符。
const handleClick = (event, index) => {
const arr = [... anchors]
arr[index] = event.target
setAnchors(arr)
}
const handleClose = (index) => {
const arr = [... anchors]
arr[index] = null
setAnchors(arr)
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
11196 次 |
| 最近记录: |