REACT and STORE with HOOKS
Tags: react, strore, javascript, pattern
Published: 2020-10-28 08:00:30

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

```jsx
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"));
```
[codesandbox](https://codesandbox.io/s/floral-currying-g5es9)

- 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

```jsx
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"));
```
[codesandbox](https://codesandbox.io/s/source-of-truth-forked-br25z?file=/index.js:0-1357)

- 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

{% codesandbox 3-order-0f0u8 view=editor %}

- 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

{% codesandbox 4-external-store-59r4i view=editor module=/api.js %}

- 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

{% codesandbox 5-multi-store-rccd4 view=editor module=/index.js %}

- 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)*