A medium-large project MUST use STORE because:
- VIEW separated from the MODEL
- You can create reusable STORES to apply to different VIEWS
- VIEW clean from code
- NO passing parent-child events e NO long PROPS
- Resources accessible from anywhere in the program
- Centralized resources that are easy to maintain
- Simplification of tests thanks to STATE
... MUST use the STORES !!!
Let's do it the way we like it:
without using a ton of frameworks!
Centralized management of DATA SOURCE
We want a DATA SOURCE accessible from any COMPONENTS
So: let's use PROVIDERS!
REACT has them, it would be rude not to
import React, { useContext, useState } from "react";
import ReactDOM from "react-dom";
// create CONTEXT
const MyContext = React.createContext();
// component that modifies the DATA SOURCE
function ChangeSource() {
const [value, setValue] = useContext(MyContext);
return <button onClick={(e) => setValue("value changed")}>Change</button>;
}
// component that displays the DATA SOURCE
function ShowSource() {
const [value, setValue] = useContext(MyContext);
return <div>{value}</div>;
}
// APPLICATION
function App() {
// create DATA SOURCE
const [value, setValue] = useState("start value");
// application
return (
// instantiate CONTEXT
<MyContext.Provider value={[value, setValue]}>
{/* modify DATA SOURCE */}
<ChangeSource />
{/* view DATA SOURCE */}
<ShowSource />
</MyContext.Provider>
);
}
ReactDOM.render(<App />, document.querySelector("#app"));
- I create CONTEXT and DATA SOURCE
- I insert the DATA SOURCE in the CONTEXT
- I insert the CONTEXT in the APP (as PROVIDER)
- And now I can access CONTEXT from any COMPONENT!
- Once the CONTEXT has been obtained I can modify the DATA SOURCE
- Changes are notified to the COMPONENTS that display the DATA SOURCE
All very nice!
Hook useReduce
For complexities greater than a single variable
it is convenient to use REDUCERS
import React, { useContext, useReducer, useState } from "react";
import ReactDOM from "react-dom";
// create CONTEXT
const MyContext = React.createContext();
// component that modifies the DATA SOURCE
function ChangeSource() {
const [state, dispatch] = useContext(MyContext)
const setValue1 = state => ({ ...state, value1: `${state.value1} changed`})
const setValue2 = state => ({ ...state, value2: `${state.value2} changed`})
return (<div>
<button onClick={(e) => dispatch(setValue1)}>
Change 1
</button>
<button onClick={(e) => dispatch(setValue2)}>
Change 2
</button>
</div>);
}
// component that displays the DATA SOURCE
function ShowSource() {
const [state, dispatch] = useContext(MyContext);
return (<div> <div>{state.value1}</div><div>{state.value2}</div> </div>)
}
// simple reducer multipurpose :)
const reducer = (state, action) => action(state)
// APPLICATION
function App() {
// create REDUCER (DATA SOURCE and DISPATCH)
const [state, dispatch] = useReducer(reducer, {
value1: "value 1",
value2: "value 2"
});
// application
return (
// instantiate CONTEXT
<MyContext.Provider value={[state, dispatch]}>
{/* modify DATA SOURCE */}
<ChangeSource />
{/* view DATA SOURCE */}
<ShowSource />
</MyContext.Provider>
);
}
ReactDOM.render(<App />, document.querySelector("#app"));
- I replace "useState" with "useReducer"
- Now I can "share" thanks to CONTEXT: STATE and DISPATCH
- STATE contains a DATA SOURCE more structured
- DISPATCH allows you to modify STATE with "pure functions"
- The REDUCER simply passes the DATA SOURCE to the DISPATCH
that's all! You just have to "put in order"
Let's put it in order
- Components are defined in external files
- The STORE is defined in store.js
...easy
Use the STORE outside of REACT
Sooner or later it will happen! So it's best to think about it right away
- I make the REDUCER global
- When needed I apply the REDUCER to the STORE
Useful when I have some AJAX stuff and I have to put it in the STORE
(and I am not in a REACT-COMPONENT: no hook!)
Multi STORE
- In the COMPONENTS (VIEW) THERE IS NO CODE !!! But only LOVE for the STORE
Yes I know: it looks like VUEX... I like VUEX!
(Forgive my bad English)
Top comments (0)