【发布时间】:2019-07-23 18:03:53
【问题描述】:
这是一个有点开放式的问题,因为我确信我处理这个问题的方式是不正确的。但我很好奇为什么 React 没有像我预期的那样重新渲染。我怀疑这与 useState 钩子与功能组件配对的行为有关。
代码在这个CodeSandbox链接中,代码如下:
function App() {
var foosList = ["foo1", "foo2", "foo3"];
const [selectedFoo, setSelectedFoo] = useState(-1);
const isSelected = i => i === selectedFoo;
return (
<div className="App">
<FoosWrapper>
<TitleSpan>Foos</TitleSpan>
<ListGroup>
{foosList.map((fooItem, i) => (
<ListGroupItem
key={fooItem}
active={isSelected(i)}
onClick={() => setSelectedFoo(i)}
>
{fooItem}
</ListGroupItem>
))}
</ListGroup>
</FoosWrapper>
<BarsWrapper>
<TitleSpan>Bars</TitleSpan>
<Bars foo={foosList[selectedFoo]} />
</BarsWrapper>
</div>
);
}
const Bars = props => {
const [pendingBar, setPendingBar] = useState("");
const [newBars, setNewBars] = useState([]);
const keyPress = e => {
if (e.key === "Enter") {
save(pendingBar);
}
};
const save = bar => {
newBars.push(bar);
setNewBars([...newBars]);
};
return (
<div>
<ListGroup>
<ListGroupItem key={props.foo}>{props.foo}</ListGroupItem>
</ListGroup>
<ListGroup>
{newBars.map(newBar => (
<ListGroupItem key={newBar}>{newBar}</ListGroupItem>
))}
</ListGroup>
<InputGroup>
<Input
placeholder="Add a bar"
onChange={e => setPendingBar(e.target.value)}
onKeyPress={keyPress}
/>
</InputGroup>
</div>
);
};
广义上讲,有两个逻辑小部件:Foos 和 Bars。 Foos 在左边,Bars 在右边。我想让用户选择一个“foo”,并在右侧显示与该“foo”相关联的不同条形列表。用户可以将新条添加到每个相应的“foo”。可以认为foo 与bar 有父关系。
Bars 组件维护用户添加的条形列表。我的期望是Bars 组件会在选择新的 foo 时重新渲染内部的newBars 集合。但是,无论在左侧选择什么“foo”,该状态都会一直存在并显示。
这看起来很奇怪,但也许我没有以正确的方式考虑 React 功能组件和钩子。很想了解为什么会存在这种行为,并且其他人很想听听更有意义的建议方法。
非常感谢任何见解!
【问题讨论】:
-
"可以认为 foo 与 bar 有父关系。"这种关系在您的代码中没有反映。您有 2 个用于 foos 和用于 bar 的单独数组。您的期望是正确的
Bars组件在您更改foo时重新渲染,但useState不会重新初始化新状态(因为这不是状态)。如果您想重新创建状态,请使用键 codesandbox.io/s/foos-and-bars-hierarchy-example-wqi0s 但这会在 foo 更改时擦除条。如果您想真正了解 foo 和 bar 之间的关系,或者将 bar 提升到App状态。 -
^^^ 正确链接演示了密钥用法 codesandbox.io/s/foos-and-bars-hierarchy-example-rvoqq 尚未保存更改 :)
标签: javascript reactjs react-hooks