英文:
Using React, React Router, and React Relay which should I use to store and retrieve state?
问题
我目前正在使用React与React Router以及React Relay。这些都有更新/传递数据的方法。React使用useState
,React Router使用其pushState
包装器(location.state
),Relay使用其updater()
方法。
但我不确定应该使用哪个来处理全局状态(如果有的话)。我的应用的所有页面都需要一个特定的ID,这不是一个会话ID。想象一个具有5个步骤的表单。第1步没有ID,第2步在成功提交后获取ID,现在在第3-5步中,它需要将该ID呈现为隐藏输入(以示例)。让我们称之为formId
。
目前,我正在使用React Router的location.state
来传递它,但感觉不对。相反,我觉得我应该有一种方法在设置了formId
后获取它。如果formId
为null,则将它们发送到第1步,如果不为null,则让当前页面/路由加载。
当然,我可以使用window.formId
,但那似乎是最不合适的方法。
英文:
I'm currently using React with React Router and React Relay. Each of these has ways of updating/passing data. React with useState
, React Router with it's pushState wrapper (location.state
), and Relay with it's updater()
method.
I'm unsure however which I should be using to handle a global state (if any at all). There is a particular ID that all pages of my app need that is not a session. Imagine a form with let's say 5 steps. Step 1 has no ID, Step 2 gets the ID on successful submit, and now on steps 3-5 it needs that ID to be rendered into a hidden input (as an example). Let's call it formId
.
Currently, I'm passing it using React Router with location.state
but it feels wrong. Instead I feel like I should have a way to get this formId
once it's set. If formId
is null send them to Step 1 and if it's not null let the current page/route load.
Of course, I could use window.formId
but that seems to most wrong.
答案1
得分: 1
我使用了React的Context API。它看起来像这样:
// FormIdContext.tsx
import React, { createContext, useState, useContext } from 'react';
interface FormIdContextType {
formId: string | null;
setFormId: (formId: string | null) => void;
}
const FormIdContext = createContext<FormIdContextType | undefined>(undefined);
// 用于消费FormIdContext的自定义钩子
export function useFormIdContext(): FormIdContextType {
const context = useContext(FormIdContext);
if (!context) {
throw new Error('useFormIdContext必须在FormIdContext.Provider内部使用');
}
return context;
}
export function FormIdProvider(props: React.PropsWithChildren<{}>) {
const [formId, setFormId] = useState<string | null>(null);
return (
<FormIdContext.Provider value={{ formId, setFormId }}>
{props.children}
</FormIdContext.Provider>
);
}
然后在我的路由器中:
// App.tsx
import React, { useState } from 'react';
import { BrowserRouter as Router, Route } from 'react-router-dom';
import Step1 from './Step1';
import Step2 from './Step2';
import Step3 from './Step3';
import FormIdContext from './FormIdContext';
function App() {
const [formId, setFormId] = useState<string | null>(null);
return (
<Router>
<FormIdContext.Provider value={{ formId, setFormId }}>
<Route path="/step1" component={Step1} />
<Route path="/step2" component={Step2} />
<Route path="/step3" component={Step3} />
</FormIdContext.Provider>
</Router>
);
}
export default App;
然后我可以像这样获取和设置这些值:
// Step3.tsx
import React from 'react';
import { useHistory } from 'react-router-dom';
import { useFormIdContext } from './FormIdContext';
function Step3() {
const history = useHistory();
const { formId, setFormId } = useFormIdContext();
const handleFormSubmission = () => {
// 假设你有表单数据并且想执行一些提交逻辑
// 一旦提交成功并且你获取了formId,你可以更新状态
const newFormId = 'new_generated_form_id';
setFormId(newFormId);
// 可选地,你可以导航到另一页或执行其他操作
// 在这里,我们只是回到Step2作为示例
history.push('/step2');
};
return (
<div>
{/* 可能使用formId的第3步内容 */}
<h1>第3步</h1>
<p>当前formId:{formId}</p>
<button onClick={handleFormSubmission}>提交表单</button>
</div>
);
}
export default Step3;
希望这些帮助!
英文:
I ended up using React's Context API.
It looked something like this
// FormIdContext.tsx
import React, { createContext, useState, useContext } from 'react';
interface FormIdContextType {
formId: string | null;
setFormId: (formId: string | null) => void;
}
const FormIdContext = createContext<FormIdContextType | undefined>(undefined);
// A custom hook to consume the FormIdContext
export function useFormIdContext(): FormIdContextType {
const context = useContext(FormIdContext);
if (!context) {
throw new Error('useFormIdContext must be used within a FormIdContext.Provider');
}
return context;
}
export function FormIdProvider(props: React.PropsWithChildren<{}>) {
const [formId, setFormId] = useState<string | null>(null);
return (
<FormIdContext.Provider value={{ formId, setFormId }}>
{props.children}
</FormIdContext.Provider>
);
}
Then in my router
// App.tsx
import React, { useState } from 'react';
import { BrowserRouter as Router, Route } from 'react-router-dom';
import Step1 from './Step1';
import Step2 from './Step2';
import Step3 from './Step3';
import FormIdContext from './FormIdContext';
function App() {
const [formId, setFormId] = useState<string | null>(null);
return (
<Router>
<FormIdContext.Provider value={{ formId, setFormId }}>
<Route path="/step1" component={Step1} />
<Route path="/step2" component={Step2} />
<Route path="/step3" component={Step3} />
</FormIdContext.Provider>
</Router>
);
}
export default App;
Then I can get and set those values like this
// Step3.tsx
import React from 'react';
import { useHistory } from 'react-router-dom';
import { useFormIdContext } from './FormIdContext';
function Step3() {
const history = useHistory();
const { formId, setFormId } = useFormIdContext();
const handleFormSubmission = () => {
// Assuming you have the form data and you want to perform some submission logic
// Once the submission is successful and you get the formId, you can update the state
const newFormId = 'new_generated_form_id';
setFormId(newFormId);
// Optionally, you can navigate to another page or perform other actions
// Here, we simply go back to Step2 as an example
history.push('/step2');
};
return (
<div>
{/* Your Step 3 content that may use formId */}
<h1>Step 3</h1>
<p>Current formId: {formId}</p>
<button onClick={handleFormSubmission}>Submit Form</button>
</div>
);
}
export default Step3;
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论