【问题标题】:React Router Dom deletes vales when I change page当我更改页面时,React Router Dom 会删除值
【发布时间】:2023-01-14 01:58:51
【问题描述】:

我正在创建一个使用 react-router-dom 进行导航的 REACT 应用程序,链接可以正常工作,但如果我(例如)填写表格并更改页面,那么如果我回来,这些值就消失了!

我刚才只用过几次,如果我记得很清楚,只要你不重新加载页面,它就会保存加载的值(例如,表格或研究结果),但这不是吗?

我错了吗?
是我的配置有问题吗?

【问题讨论】:

  • 在 react-router 中,Route 组件简单地检查 URL,如果匹配(URL 以路径开头),那么它将渲染传递的组件。

标签: reactjs react-router-dom


【解决方案1】:

是的,就 React Router 的底层工作方式而言,这是意料之中的事情。 React Router 只会挂载符合路由器标准的组件,并从节点树和 DOM 中删除其他路由。

如果你想保持这些值,你需要保持它们的状态比路由更长。一种方法是使用 renderRoute 形式,这样您就可以将有状态值直接与路由器相邻,而不是将它们保留在路由的子组件中。另一种方法是使用像 Redux 这样的东西来保持组件外部的状态,从而延长寿命。

我在下面创建了一个示例来演示如何使用 3 种不同的方法。如果您在 Home 和 Forms 之间来回切换,其中 2 个的值将保持不变,但不存在的值将重置。

  • form-without-persistence 不会坚持下去。它使用一个组件,其状态将在每个安装周期(更改路由)中被丢弃。
  • form-with-render-persistence 将其状态保留在呈现 Router 的组件中,因此即使我们在不在其路线上时停止呈现它,它的状态也将继续存在。这对于小数据集是可以的,但你必须保持全部这里的数据意味着路由器中有很多useState(),特别是如果您有多种形式。
  • form-with-context-persistence 将保留其状态,因为它使用 [Context] 来存储数据,这使数据远离 Router 组件但仍可检索。示例 Context 非常初级,但演示了与 Formik 或 Redux 之类的东西相同的概念。

const {createContext, useState, useContext} = React;
const {render} = ReactDOM;
const {BrowserRouter: Router, Route, Link} = ReactRouterDOM;

const formContext = createContext([
    "",
    () => console.log("Would set name")
]);

const {Provider: FormProvider} = formContext;

const Form = ({children}) => {
    const nameState = useState("");
    return <FormProvider value={nameState} children={children} />;
};

const useFormContext = () => useContext(formContext);

const FormWithoutPersistence = () => {
    const [name, setName] = useState("");

    return (
        <form onSubmit={e => {
            e.preventDefault();
            console.log("You tried to submit");
        }}>
            <fieldset>
                <legend>Form Fields</legend>
                <div>
                    <label>
                        <span>Name</span>
                        <input
                            type="text"
                            value={name}
                            onChange={e => setName(e.target.value)}
                        />
                    </label>
                </div>
            </fieldset>
            <button type="submit">Submit</button>
        </form>
    );
};

const FormWithContextPersistence = () => {
    const [name, setName] = useFormContext();

    return (
        <form onSubmit={e => {
            e.preventDefault();
            console.log("You tried to submit");
        }}>
            <fieldset>
                <legend>Form Fields</legend>
                <div>
                    <label>
                        <span>Name</span>
                        <input
                            type="text"
                            value={name}
                            onChange={e => setName(e.target.value)}
                        />
                    </label>
                </div>
            </fieldset>
            <button type="submit">Submit</button>
        </form>
    );
};

const App = () => {
    const [name, setName] = useState("");

    return (
        <Router>
            <nav>
                <ul>
                    <li><Link to="/">Home</Link></li>
                    <li><Link to="/form-without-persistence">Form without persistence</Link></li>
                    <li><Link to="/form-with-render-persistence">Form with render persistence</Link></li>
                    <li><Link to="/form-with-context-persistence">Form with context persistence</Link></li>
                </ul>
            </nav>
            <Route exact path="/" render={() => (
                <div>
                    <p>I'm the home page!</p>
                </div>
            )} />
            <Route path="/form-without-persistence" component={FormWithoutPersistence} />
            <Route path="/form-with-render-persistence" render={() => (
                <form onSubmit={e => {
                    e.preventDefault();
                    console.log("You tried to submit");
                }}>
                    <fieldset>
                        <legend>Form Fields</legend>
                        <div>
                            <label>
                                <span>Name</span>
                                <input
                                    type="text"
                                    value={name}
                                    onChange={e => setName(e.target.value)}
                                />
                            </label>
                        </div>
                    </fieldset>
                    <button type="submit">Submit</button>
                </form>
            )} />
            <Route path="/form-with-context-persistence" component={FormWithContextPersistence} />
        </Router>
    );
};

render(
    <Form><App /></Form>,
    document.getElementById("app")
);
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/react-router-dom@5.2.0/umd/react-router-dom.js"></script>

<div id="app"></div>

【讨论】:

  • 非常感谢!超级清晰!我总是使用redux,但我认为持久化是由router 完成的。我刚刚在应用程序中实现了redux,所以我将尝试查看差异。
【解决方案2】:

值正在重置的事实与 react-router-dom 无关。你没有在这里发布你的代码,但我猜你的每条路线都会呈现不同的组件。

这意味着当您通过按 &lt;Link /&gt; 更改路由时,当前组件(例如,包含表单的组件)将被卸载,因此其所有状态都将被删除。当您返回此链接时,组件会重新挂载,但在卸载时它已经丢失了数据。

如果你想在页面之间保留数据,我建议使用 React 的 Context API,或者一个全局存储库,如 React ReduxMobX

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-02
    • 2020-04-29
    • 2021-01-22
    • 1970-01-01
    • 2018-12-03
    • 2021-02-19
    • 2017-09-12
    • 2020-07-09
    相关资源
    最近更新 更多