【问题标题】:React createContext/useContext does not survive between pagesReact createContext/useContext 在页面之间无法生存
【发布时间】:2019-06-15 08:32:32
【问题描述】:

我正在尝试为应用所需的所有组件创建一个共享的全局状态,而不是依赖于 props 钻取或 redux,我正在尝试使用 React Context 来实现。

当我在路由之间切换时,为什么我的用户上下文无法生存?下面的应用程序说明了这个问题。

我是否需要将任何其他挂钩与useContext 结合使用?

//index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { AuthenticationProvider }  from "./AuthenticationProvider";

const Index = () => {
    return (
      <AuthenticationProvider>
        <App />
      </AuthenticationProvider>
    );
}

ReactDOM.render(<Index />, document.getElementById('root'));
//App.js
import React, { useState, useContext } from 'react';
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import './App.css';
import { AuthenticationContext } from './AuthenticationProvider';

function AddUser() {

  const [formUser, setFormUser] = useState("");

  const [user, setUser] = useContext(AuthenticationContext);

  const handleSubmit = async (event) => {
    event.preventDefault();
    setUser(formUser);
  }

  return (
    <React.Fragment>
      Form user: {formUser}.
          <form id="form1" onSubmit={handleSubmit}>
        <input type="text" id="user" onChange={event => setFormUser(event.target.value)} />
        <input type="submit" value="Save" />
      </form>
      <br/>
      Current user: {user}
      <br/>
      <a href="/">Back to home</a>
    </React.Fragment>
  );
}

function Home() {

  const [user, setUser] = useContext(AuthenticationContext);

  return (
    <React.Fragment>
      <div className="App">
        Hello {user}.
        <br/>
        <a href="/add">Add user</a>
    </div>
    </React.Fragment>
  );
}

function App() {
  return (
    <Router>
      <Switch>
        <Route exact path="/" component={Home} />
        <Route exact path="/add" component={AddUser} />
      </Switch>
    </Router>
  );
}

export default App;

//AuthenticationProvider.js
import React, { useState, createContext } from "react";

const DEFAULT_STATE = "";

export const AuthenticationContext = createContext(DEFAULT_STATE);

export const AuthenticationProvider = ({ children }) => {
  const [user, setUser] = useState(DEFAULT_STATE);

  return (
    <AuthenticationContext.Provider value={[user, setUser]} >
      {children}
    </AuthenticationContext.Provider>
  );
}

【问题讨论】:

    标签: reactjs react-hooks


    【解决方案1】:

    问题在于您使用常规的&lt;a&gt; 链接来浏览应用程序,并且每次从Home 转到addUser 时应用程序都会刷新。要在不刷新页面的情况下浏览应用程序,请使用 react-router-dom 中的 Link 组件

    HomeAddUser 中将a 链接更改为Link 组件

    import { Link } from "react-router-dom";
    
    function Home() {
      const { user, setUser } = useContext(AuthenticationContext);
    
      return (
        <React.Fragment>
          <div className="App">
            Hello {user}.
            <br />
            <Link to="/add">Add user</Link> <-- Changed a to Link
          </div>
        </React.Fragment>
      );
    }
    
    function AddUser() {
    
      const [formUser, setFormUser] = useState("");
    
      const [user, setUser] = useContext(AuthenticationContext);
    
      const handleSubmit = async (event) => {
        event.preventDefault();
        setUser(formUser);
      }
    
      return (
        <React.Fragment>
          Form user: {formUser}.
              <form id="form1" onSubmit={handleSubmit}>
            <input type="text" id="user" onChange={event => setFormUser(event.target.value)} />
            <input type="submit" value="Save" />
          </form>
          <br />
          Current user: {user}
          <br />
          <Link to="/">Back to home</Link> <-- Changed a to Link
        </React.Fragment>
      );
    }
    

    【讨论】:

    • 这是否意味着如果用户刷新页面或点击某个链接时上下文消失了?如果我不刷新页面,是不是和只使用 useState 挂钩一样?在实际应用中我使用 react-bootstrap 和 NavDropdown.Item 组件进行导航,在这种情况下会发生什么?
    • 如果用户刷新页面,应用程序会重置,因此您将失去任何状态是的,要导航到不同的页面而不刷新页面,您必须使用来自react-router-domLink 组件,如果您想要在刷新之间保留用户状态,可以将其保存到 localStorage
    • @Pablo 你可以使用react-router-bootstrap 用路由器包装引导链接
    • 感谢@Asaf。因此,如果我理解正确,useContext 的目的是创建所有组件都可以使用的共享全局道具,只要该上下文仍在内存中,即没有浏览器刷新?
    • @Pablo context 的目的是为我们提供一种通过组件树访问捕获值的简单方法,方法是将它们传递给提供程序并从我们需要的任何组件调用useContext而不是作为道具深入到我们需要它们的地方。当我们刷新页面时,应用程序状态将重置,与context 无关,而是作为我们应用程序的一般状态。这就是为什么我们需要使用来自react-router-domLink 组件来防止刷新页面并重新启动我们的React App
    猜你喜欢
    • 1970-01-01
    • 2021-11-12
    • 1970-01-01
    • 2020-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-03
    • 1970-01-01
    相关资源
    最近更新 更多