React节点处于保持记住道具的状态



调试此代码时遇到问题。

我有一个应用程序组件:

function App() {
const [state, setState] = useState(0);
const onSelectItem = () => {
console.log("🐞: onSelectItem -> currentState", state);
};
// items is an array of ReactNode: button, when click on it. It will log the currentState.
const items = ["FirstItem", "SecondItem"].map(item =>  (
<button key={item} onClick={() => onSelectItem()}>
{item}
</button>
);
);
return (
<div className="App">
<Menu items={items} />
<hr />
<button onClick={() => setState(prevState => prevState + 1)}>Change State</button>
</div>
);
}

我的Menu组件将接收items道具,并对其进行渲染。它还可以设置活动项。为了简单起见,我渲染了一个button来将activeItem设置为第一个。活动项目也将被渲染。

function Menu({ items }) {
const [activeItem, setActiveItem] = useState(items[0]);
return (
<div>
{items}
<hr />
{activeItem}
</div>
);
}

现在,进入主要部分:

  • 我按下按钮(在hr之前(=>它显示currentState(OK(
  • 我按下活动按钮(在hr之后(=>它显示currentState(OK(
  • 我按下更改状态按钮=>状态现在变为1(OK(
  • 现在,如果我按下按钮(在hr之前(=>它显示currentState为1(OK(
  • 但是,如果我按下活动按钮(在hr之后(=>它仍然显示0(这是最后一个状态((??(

我的猜测是React在使用useState时会记住所有内容。但我不确定。有人能为我解释一下吗!

我还为您提供了一些片段,以便您轻松理解我的问题。

const {useState} = React;
function Menu({ items }) {
const [activeItem, setActiveItem] = useState(items[0]);
return (
<div>
{items}
<hr />
<span>Active Item:</span>
{activeItem}
</div>
);
}
function App() {
const [state, setState] = useState(0);
console.log(state);
const onSelectItem = () => {
console.log("🐞: onSelectItem -> currentState", state);
};
const items = ["FirstItem", "SecondItem"].map(item => {
return (
<button key={item} onClick={() => onSelectItem()}>
{item}
</button>
);
});
return (
<div className="App">
<Menu items={items} />
<hr />
<button onClick={() => setState(prevState => prevState + 1)}>Change State</button>
</div>
);
}
ReactDOM.render(<App />, document.getElementById('app'));
<div id="app"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>

您正试图从Menu组件中的App组件访问状态。

State是该组件的本地状态,不能在外部访问,如果您想访问组件外部的状态,可以参考useContext钩子实现。

https://reactjs.org/docs/hooks-reference.html#usecontext

您看到0处于活动状态的原因是这是useState的默认值。

您需要将键传递到菜单组件。

每当道具发生变化时,组件都必须使用新道具重新渲染。

请参阅他们官方文件中的这篇文章-https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#recommendation-完全不受控制的组件-带密钥

我所做的改变是将状态作为键传递给菜单组件

const {useState} = React;
function Menu({ items }) {
const [activeItem, setActiveItem] = useState(items[0]);
return (
<div>
{items}
<hr />
<span>Active Item:</span>
{activeItem}
</div>
);
}
function App() {
const [state, setState] = useState(0);
console.log(state);
const onSelectItem = () => {
console.log("🐞: onSelectItem -> currentState", state);
};
const items = ["FirstItem", "SecondItem"].map(item => {
return (
<button key={item} onClick={() => onSelectItem()}>
{item}
</button>
);
});
return (
<div className="App">
<Menu items={items} key={state}/>
<hr />
<button onClick={() => setState(prevState => prevState + 1)}>Change State</button>
</div>
);
}
ReactDOM.render(<App />, document.getElementById('app'));
<div id="app"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>

最新更新