我正在学习React并使用上下文构建一个项目。最初,我在App.js组件中构建上下文,但为了使App.js更清晰,我希望将其分离到自己的文件中。然而,我很难弄清楚这是如何做到的,或者甚至是可能的。我认为我被卡住的部分是如何提供上下文。我在下面粘贴了新的上下文文件和App.js,其中注释掉了原始的上下文结构。有人知道我是怎么做到这一点的吗?
// TaskManipulatorContext
import React, { useReducer } from "react";
import AddTask from "../Components/dnd_components/AddTask";
export const TaskManipulatorContext = React.createContext();
const taskManipulatorInitialState = {
panelData: {
height: 50,
open: false,
title: "title",
content: "content",
},
newTask: false,
deleteTask: false,
taskContainer: null,
};
const taskManipulatorReducer = (state, action) => {
switch (action.type) {
case "addTask-botPanel":
// Brings up bottom panel to add new task
return {
...state,
panelData: {
...state.panelData,
height: 20,
open: true,
title: "Add Task",
content: <AddTask />,
},
taskContainer: {
...state.taskContainer,
...action.value,
},
};
case "addTask-submitTask":
// Submits task and adds it to list
return {
...state,
panelData: {
...state.panelData,
closing: true,
},
newTask: true,
taskContainer: {
...state.taskContainer,
newTask: action.value,
},
};
case "reset":
// Reset back to initial state
return taskManipulatorInitialState;
default:
return taskManipulatorInitialState;
}
};
const [state, dispatch] = useReducer(
taskManipulatorReducer,
taskManipulatorInitialState
);
// App.js
import React, { useContext } from "react";
import "./index.css";
import RenderXMilageBoxes from "./Components/RenderXMilageBoxes";
import BottomPanel from "./Components/BottomPanel";
import AddTask from "./Components/dnd_components/AddTask";
import { TaskManipulatorContext } from "./Contexts/TaskManipulatorContext";
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * CONTEXTS * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// export const TaskManipulatorContext = React.createContext();
// const taskManipulatorInitialState = {
// panelData: {
// height: 50,
// open: false,
// title: "title",
// content: "content",
// },
// newTask: false,
// deleteTask: false,
// taskContainer: null,
// };
// const taskManipulatorReducer = (state, action) => {
// switch (action.type) {
// case "addTask-botPanel":
// // Brings up bottom panel to add new task
// return {
// ...state,
// panelData: {
// ...state.panelData,
// height: 20,
// open: true,
// title: "Add Task",
// content: <AddTask />,
// },
// taskContainer: {
// ...state.taskContainer,
// ...action.value,
// },
// };
// case "addTask-submitTask":
// // Submits task and adds it to list
// return {
// ...state,
// panelData: {
// ...state.panelData,
// closing: true,
// },
// newTask: true,
// taskContainer: {
// ...state.taskContainer,
// newTask: action.value,
// },
// };
// case "reset":
// // Reset back to initial state
// return taskManipulatorInitialState;
// default:
// return taskManipulatorInitialState;
// }
// };
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * MAIN COMPONENT * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
function App() {
// Contexts
// const [state, dispatch] = useReducer(
// taskManipulatorReducer,
// taskManipulatorInitialState
// );
const taskManipulatorContext = useContext(TaskManipulatorContext);
return (
<div>
<taskManipulatorContext.Provider
value={{
state,
dispatch,
}}
>
<RenderXMilageBoxes currentMiles={5001} numFutureServices={5} />
<BottomPanel panelData={state.panelData} />
</taskManipulatorContext.Provider>
</div>
);
}
export default App;
发布于 2020-06-13 22:27:17
我更喜欢这样做的方式是创建一个上下文,然后为提供者和useContext钩子提供相同的上下文,以便在组件中使用。
它看起来像这样:
TaskManiupulatorContext.js
const TaskManipulatorContext = createContext({})
// dispatcher logic
export const TaskManipulatorContextProvider = () => {
const [state, dispatch] = useReducer(
taskManipulatorReducer,
taskManipulatorInitialState
);
// You can choose to wrap this in a useMemo if you want to be extra careful about potential rerenders
const taskManipulatorContextStore = {
state,
dispatch,
}
return <TaskManipulatorContext.Provider value={taskManipulatorContextStore}>{children}</TaskManipulatorContext.Provider>
}
export const useTaskManipulatorContext = () => useContext(TaskManipulatorContext)
然后,通过使用提供者包装您的应用程序,使上下文在应用程序级别可用:
App.js
import { TaskManipulatorContextProvider } from './TaskManipulatorContext'
// app logic
const App = () => {
return (
<TaskManipulatorContextProvider>
<App />
</TaskManipulatorContextProvider>
)
}
现在,您可以从应用程序内的任何组件导入您的useTaskManipulatorContext
挂钩并使用它:
SomeComponent.js
import { useTaskManipulatorContext } from './TaskManipulatorContext'
export const SomeComponent = () => {
const taskManipulatorCtx = useTaskManipulatorContext()
const someFunctionWhichUpdatesContextState = (action) => {
taskManipulatorCtx.dispatch(action)
}
return (
<div>
<text>{'Here is some state from the context'}</text>
<text>{taskManipulatorCtx.state}</text>
</div>
)
}
请注意,采用这种方法可以在很大程度上控制上下文中的访问模式。例如,如果您不希望组件为了更改状态而直接访问分派,您可以在提供程序中创建一个方法来分派某些操作,并将其导出为您的函数可以使用的方法(即。您不需要依赖您的组件或使用您的组件的开发人员来了解如何更新状态的确切行为/实现)。
const taskManipulatorContextStore = {
state,
addTask: (taskToAdd) = dispatch(actions.add, taskToAdd)
}
https://stackoverflow.com/questions/62365993
复制