admin管理员组文章数量:1391991
I am learning React and building a project using context. Originally I build the context in the App.js ponent but I want to separate it into its own file to keep App.js cleaner. However, I am having trouble figuring out how this is done or if its even possible. I think the part I am stuck on is how to provide to the context. I pasted my new Context file below along with App.js with the original Context structure mented out. Does anyone know how I can acplish this?
// TaskManipulatorContext
import React, { useReducer } from "react";
import AddTask from "../Components/dnd_ponents/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_ponents/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;
I am learning React and building a project using context. Originally I build the context in the App.js ponent but I want to separate it into its own file to keep App.js cleaner. However, I am having trouble figuring out how this is done or if its even possible. I think the part I am stuck on is how to provide to the context. I pasted my new Context file below along with App.js with the original Context structure mented out. Does anyone know how I can acplish this?
// TaskManipulatorContext
import React, { useReducer } from "react";
import AddTask from "../Components/dnd_ponents/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_ponents/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;
Share
Improve this question
asked Jun 13, 2020 at 21:53
Notorious776Notorious776
5039 silver badges25 bronze badges
1 Answer
Reset to default 8My preferred way of doing this is to create a context, then provide the same context to both a Provider and a useContext hook to consume in ponents.
It would look something like this:
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)
Then make the context available at the app level by wrapping your app with the provider:
App.js
import { TaskManipulatorContextProvider } from './TaskManipulatorContext'
// app logic
const App = () => {
return (
<TaskManipulatorContextProvider>
<App />
</TaskManipulatorContextProvider>
)
}
Now, from any ponent inside the App, you can import your useTaskManipulatorContext
hook and consume it:
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>
)
}
Note that taking this approach gives you a lot of control over the access patterns inside of the Context. For example, if you don't want ponents to have direct access to the dispatch in order to change state, you can create a method inside your Provider which dispatches some action, and export it as a method which your functions can consume (ie. you don't rely on your ponents, or developers consuming your ponents, to know the exact behavour/implementation of how to update state).
const taskManipulatorContextStore = {
state,
addTask: (taskToAdd) = dispatch(actions.add, taskToAdd)
}
本文标签: javascriptHow do I create a React Context in its own individual fileStack Overflow
版权声明:本文标题:javascript - How do I create a React Context in its own individual file? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744758461a2623606.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论