如何在 React Router 6 中将状态提升?

huangapple go评论141阅读模式
英文:

How to Lift State Up w/ React Router 6?

问题

我在思考如何在我的两个路由之间共享状态。我应该将状态从我的AddContact组件提升到LayoutApp以便分享给ContactList。我的Layout组件只渲染一个HeaderOutlet组件。

英文:

I am wondering how to share state between my two routes. Should I lift state up from my AddContact component to Layout or App to share to ContactList. My Layout component is just rendering a Header and Outlet component.

function App() {
  const [contacts, setContacts] = useState([])

  return (
    <BrowserRouter>
      <Routes>
        <Route element={<Layout />}>
          <Route path='/' element={<ContactList />} />
          <Route path='/add' element={<AddContact />} />
        </Route>
      </Routes>
    </BrowserRouter>
  );
}

答案1

得分: 3

你可以将状态提升到 App,然后将需要的内容作为 props 传递给每个路由组件。

示例:

function App() {
  const [contacts, setContacts] = useState([]);

  return (
    <BrowserRouter>
      <Routes>
        <Route element={<Layout />}>

          <Route
            path="/"
            element={<ContactList contacts={contacts} />}
          />

          <Route
            path="/add"
            element={<AddContact setContacts={setContacts} />}
          />

        </Route>
      </Routes>
    </BrowserRouter>
  );
}

另一种方法是将状态存储在 Layout 布局路由组件中,并通过 Outlet 组件的上下文来提供。路由组件可以通过 useOutletContext 钩子访问提供的上下文值。

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route element={<Layout />}>

          <Route path="/" element={<ContactList />} />

          <Route path="/add" element={<AddContact />} />

        </Route>
      </Routes>
    </BrowserRouter>
  );
}
const Layout = () => {
  const [contacts, setContacts] = useState([]);

  return (
    ...
    <Outlet context={{ contacts, setContacts }} />
    ...
  );
};
const ContactList = () => {
  const { contacts } = useOutletContext();

  ...
};
const AddContact = () => {
  const { setContacts } = useOutletContext();

  ...
};

这主要取决于个人喜好或范围,例如,子 React 树中需要多少部分访问状态。

英文:

You could lift it to either.

If lifting state to App you can pass what you need down as props to each routed component.

Example:

function App() {
  const [contacts, setContacts] = useState([]);

  return (
    &lt;BrowserRouter&gt;
      &lt;Routes&gt;
        &lt;Route element={&lt;Layout /&gt;}&gt;
          &lt;Route
            path=&quot;/&quot;
            element={&lt;ContactList contacts={contacts} /&gt;}
          /&gt;
          &lt;Route
            path=&quot;/add&quot;
            element={&lt;AddContact setContacts={setContacts} /&gt;}
          /&gt;
        &lt;/Route&gt;
      &lt;/Routes&gt;
    &lt;/BrowserRouter&gt;
  );
}

The alternative is to locate the state in the Layout layout route component and expose via the Outlet component's context. The routed components would access the provided context value via the useOutletContext hook.

function App() {
  return (
    &lt;BrowserRouter&gt;
      &lt;Routes&gt;
        &lt;Route element={&lt;Layout /&gt;}&gt;
          &lt;Route path=&quot;/&quot; element={&lt;ContactList /&gt;} /&gt;
          &lt;Route path=&quot;/add&quot; element={&lt;AddContact /&gt;} /&gt;
        &lt;/Route&gt;
      &lt;/Routes&gt;
    &lt;/BrowserRouter&gt;
  );
}
const Layout = () =&gt; {
  const [contacts, setContacts] = useState([]);

  return (
    ...
    &lt;Outlet context={{ contacts, setContacts }} /&gt;
    ...
  );
};
const ContactList = () =&gt; {
  const { contacts } = useOutletContext();

  ...
};
const AddContact = () =&gt; {
  const { setContacts } = useOutletContext();

  ...
};

It basically comes down to preference, or scope in my opinion, e.g. how much of the sub-ReactTree needs to access the state.

答案2

得分: 1

以下是已翻译的内容:

这里有一个示例,使用状态而不是状态管理系统。

假设我们有两个兄弟组件:page1 和 page2。如果我们需要将数据从 page1 组件传递到 page2 组件,我们可以在 react-router-dom v6 中使用 hooks。

import { Link } from 'react-router-dom';

const Page1 = () => {
  return (
    <Link to='/page2' state={{ msg: "来自page1的问候" }}>前往 Page2</Link>
  );
}

export default Page1;

在 page2 组件中,您可以像这样接收对象。

import { useLocation } from "react-router-dom";

const Page2 = (props) => {
   const { state } = useLocation();
   
   return <div>{state.msg}</div>
}
  
export default Page2;
英文:

Here is an example using states and not state management systems.

Let's assume that we've got 2 sibling components; page1 and page2. If we need to pass data from the page1 component to the page2 component, we can use hooks in react-router-dom v6.

import {Link} from &#39;react-router-dom&#39;;

const Page1 = () =&gt; {
  return (
    &lt;Link to={&#39;/page2&#39;} state: {msg: &quot;hello from page1&quot;}&gt;Go to Page2&lt;/Link&gt;
  );
}

export default Page1;

On the page2 component, you can receive the object like that.

import { useLocation } from &quot;react-router-dom&quot;;

const Page2 = (props) =&gt; {
   const { state } = useLocation();
   
   return &lt;div&gt;{state.msg}&lt;/div&gt;
 
}

export default Page2;

huangapple
  • 本文由 发表于 2023年3月7日 13:24:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/75658306.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定