useState影响组件的所有实例



下面有一个名为Idea:的简单组件

import './Idea.css';
import { useState } from 'react';
import { useParams } from 'react-router-dom';
function Idea() {
const { id } = useParams();
const [ test, setTest ] = useState('');
console.log('Idea rendered');
const handleChange = (event) => {
setTest(event.target.value);
};

return (
<form>
<input onChange={handleChange} value={test}/>
</form>
);
};
export default Idea;

该组件的每个实例都是通过动态路由使用react路由器呈现的,如下面的第二个路由组件所示:

function App() {
return (
<Provider store={store}>
<BrowserRouter>
<main>
<SideBar />
<section id='main-window'>
<Routes>
<Route exact path="/" element={ <Instructions /> } />
<Route path="/ideas/:id" element={ <Idea/> } />
</Routes>
</section>
</main>
</BrowserRouter>
</Provider>
);
};

这个问题在这个例子中得到了说明:假设我在/inideas/1234的路线上,它的输入值显示你好,世界。如果我切换到路由/iides/5678,那么该路由上的输入也会说你好,世界即使我在渲染时指定了输入值。如果我更改路线/iides/5678上的输入值,路线/input/1234的输入值也将更改。无论路线如何,它们都将不可避免地具有相同的价值,就像它们是相同的一样。当我在Idea组件中引入useState钩子时,这种情况就开始发生了。我认为useState应该在每次更改路由时重置输入值,但这似乎并没有发生。

以下是useState挂钩的文档:https://reactjs.org/docs/hooks-state.html

以下是您案例的重要部分:

调用useState做什么它声明了一个"状态变量"。。。这是一种在函数调用之间"保留"某些值的方法。。。通常,当函数退出时,变量"消失",但状态变量由React保留。

因此,通过在Idea组件中引入useState钩子,实际上是在保留输入值。如果您希望它根据特定条件清除,例如useParams中的id的值发生了更改,请查看useEffect挂钩。也许可以做一些类似的事情:

useEffect(()=> {
setTest('');
}, [id]);

给定路由<Route path="/ideas/:id" element={<Idea />} />,当路由路径参数id更改时,Route组件不会卸载和装载Idea的新实例,因为这会很浪费,相反,它只会使用路由上下文提供的新路由路径参数重新发送Idea

可以像其他React组件一样考虑这一点,因为以下三个原因之一:

  1. 状态更新已排入队列并触发组件重新应答器
  2. 道具值更新并触发了组件重新发布
  3. 重新绘制了零部件的父零部件

您的代码处于第三种情况,其中URL路径发生了更改,Routes组件与最佳Route组件匹配,并且由于<Route path="/ideas/:id" element={<Idea />} />已经匹配,因此它重新发送,从而重新发送Idea

如果被路由的组件需要处理对路由参数的改变,那么它应该使用CCD_;听";为他们。

示例:

function Idea() {
const { id } = useParams();
const [test, setTest] = useState('');
useEffect(() => {
console.log('Idea rendered');
});
useEffect(() => {
console.log('id updated', { id });
setTest('');
}, [id]);
const handleChange = (event) => {
setTest(event.target.value);
};

return (
<form>
<input onChange={handleChange} value={test} />
</form>
);
};

监听更改的另一种方法是创建一个包装组件,该组件使用路由参数作为路由组件上的React键。使用此方法卸载并装载新组件实例。

示例:

const IdeaWrapper = () => {
const { id } = useParams();
return <Idea key={id} />;
};

<Routes>
<Route exact path="/" element={<Instructions />} />
<Route path="/ideas/:id" element={<IdeaWrapper />} />
</Routes>

如果您愿意,您甚至可以创建一个自定义状态挂钩,在依赖关系更新时重置。

示例:

const useResetState = (initialState, deps) => {
const [state, setState] = useState(initialState);
useEffect(() => {
setState(initialState);
}, deps);
return [state, setState];
};

function Idea() {
const { id } = useParams();
const [test, setTest] = useResetState('', [id]); // <-- resets when id updates
useEffect(() => {
console.log('Idea rendered');
});
const handleChange = (event) => {
setTest(event.target.value);
};

return (
<form>
<input onChange={handleChange} value={test} />
</form>
);
};

最新更新