You are on page 1of 22

Understanding state management

State management is the philosophy that we choose to make sure that our state remain clear and
traceable over the time during the presence of the application on the browser while reading and
writing into it.
Simply said, State management maintains and stores the information of any user till the end of the
user session.

Problem of props
So we all know that React is a great library :
• It follows a component based architecture,
• It encourages lifting state up,
• It break up your UI into small components and
• It pass data from top to bottom using props.
This a good approach to build UI as it facilitates better code reuse and it makes your app more
predictable and easier to test. However there’s a caveat to that.
When you’re passing data through props from top to bottom of the component tree, you probably
experienced this frustration where you want to pass data from the top level component to a 3rd or
4th level component but you end up passing these data to components on each level of the tree.
This is what we call Prop-drilling!

Why we need a global state?


We are all familiar with the concept of a desktop on our computers right?
Just by looking at the desktop we can answer all of these questions:
• Who is the current user?
• Which applications are installed and which ones are opened?
• How many desktop icons we have and what is their position?
• What is the current date and time?

If the desktop was a React application, we could store all of these data in the state of our app.
Think about the React Global State as a JavaScript object containing all the necessary
information needed for our application view.
The state management is to maintain and store the information of the user till the session ends True
The store is :State which is global and shared between component
Props drilling refers to the process of passing the props through the component tree to deliver data
to certain component True
What is Redux?
Redux is a predictable state container for JavaScript apps.
It helps us write applications that behave consistently, run in different environments (client, server,
and native), and it is easy to test.
On top of that, it provides a great developer experience, such as live code editing combined with a
time traveling debugger.
We can use Redux together with React, or with any other view library.
Redux is lightweight library (about 2kB, including dependencies)

What can Redux do?


Many people use Redux to manage the global state in React apps. It’s the most common use case in
the wild and Redux improves the aspects where React doesn’t do well (yet).
Let’s get started by learning what state management means by Redux.

The State
If you are not sure what this state means, let’s replace it with a more generic term: data.
State is data that change from time to time. State determines what’s displayed on the user interface.
Let’s say we are building a Dribbble shot page. What is the data we want to display on the page?
They include the author’s profile photo, name, the animated GIF, the number of hearts, the
comments, and so on.

Steps:
First, we need to fetch all these data from a server in the cloud and put it somewhere. Next, we need
to actually display the data. We need to assign pieces of this data to corresponding UI elements that
represent what we actually see in the browser. For example, we assign the URL of the profile photo
to the src attribute of an HTML img tag:
<img src='https://url/to/profile_photo'>

Finally, we need to handle changes to the data. For example, if a user adds a new comment to a
Dribbble shot -or adds a star- we need to update the view accordingly.
Coordinating these three aspects of state is a big part in front-end development, and React has
various degree of support for this task. Sometimes the built-in facility in React works well enough.
But as the app grows more complex, its state may become harder to manage with React alone.
That’s why Redux is created
Aspect of data management:
In general, there are three aspects of data that we need to manage in an app:

1.Fetching and storing data


With Redux, we fetch data once and store it in a central place, conveniently called store.

1.Assigning data to UI elements


To deliver data to the destination, we have to engage all the components on the path, even if they
don’t need the data at all (Pass data to components via props).
With Redux, we can plug in any data into any component, without affecting other components.

1.Changing data
Redux allows us to divide and conquer. It provides a standard way to break data updating logic into
small “reducers”. Those reducers work harmoniously together to complete a complex action.

Fetching And Storing Data


n React, we break down a UI into components. Each of these components can be broken down into
smaller components.
If our UI is structured this way, when do we fetch the data and where to store it before
populating the UI?
magine there’s a chef living in each component. Fetching data from servers is like sourcing all
the ingredients needed to prepare dishes.
A naive way is to fetch and store the data where and when it’s needed. This is like each chef
going out to buy vegetables and meats directly from far-away farms.
This approach is wasteful. We need to call the server many times from many components even for
the same data. The chefs would waste a lot of gas and time traveling back and forth.

The store
with Redux, we fetch data once and store it in a central place, conveniently called store.
The data is then ready for use anytime by any component. This is not unlike having a superstore
nearby where our chefs can buy all the ingredients. The superstore sends trucks to carry back
vegetables and meats in bulk from farms. It’s a lot more efficient than asking individual chefs to go
to the farms themselves!
The store also serves as the single source of truth. Components always retrieve data from the store,
not from anywhere else. This keeps all the UI content consistent.
This approach is more efficient than the naive way of fetching data from every component. We
could fetch data once and located in the store

Redux allows us to divide and conquer. It provides a standard way to break data updating logic into
small reducers(we will learn more about Reducers later in this course). Those reducers work
harmoniously together to complete a complex action.

What's Action?
An action is like a message that we send (i.e. dispatch) to our central Redux store. We can think of it
as a description of what it should happen. It can literally be anything. But ideally we want to stick to
an agreed-upon pattern. And the standard pattern is as follows:
const Action = {
type: string; // Actions MUST have a type
payload?: any; // Actions MAY have a payload
error?: boolean; // Actions MAY have an error field
// when true, payload SHOULD contain an Error
};

What ‘s Reducer?
Reducers specify how the application's state changes in response to actions sent to the store.
Remember that actions only describe what happened, but don't describe how the application's state
changes. That’s the reducer job.
Example of a reducer.
const reducer = (state, action) => {
switch (action.type) {
case type1:
return; // the new state
return; // the new state
default:
return state;
}

What’s Store?
We defined the actions that represent the facts about “what happened” and the reducers that are on
charge of updating the state according to those actions.
The Store is the object that brings them together. The store has the following responsibilities:
• Holds application state;
• Allows access to state via getState();
• Allows state to be updated via dispatch(action);
• Registers listeners via subscribe(listener);
• Handles unregistering of listeners via the function returned by subscribe(listener).
Redux data flow
The image below describes the redux data flow and how every part get fired :

Redux vs react-redux
Redux gives you a store, and lets you keep state in it, and get state out, and responds when the state
changes. But that’s all it does.
It’s actually react-redux that lets you connect pieces of the state to React components.
That’s right: redux knows nothing about React at all.
These libraries are like two peas in a pod, though. 99.999% of the time, when anyone mentions
“Redux” in the context of React, they are referring to both of these libraries in tandem. So that keep
in mind, when you see Redux mentioned on StackOverflow, or Reddit, or elsewhere.
The redux library can be used outside of a React app too. It’ll work with Vue, Angular, and even
backend Node/Express apps.
To use redux, we need Redux
To use redux with react, we need Reduxreact -redux
To install react-redux, we run npm i react-reduxnpm install --save react-redux

Steps to create a global state


Learn Redux, Starting With Plain React.
We’re going to take an incremental approach, starting with a plain React app with component state,
adding parts of Redux piece-by-piece, and dealing with the errors along the way. Let’s call it “Error-
Driven Development” :)

Example:
In this example, the Counter component holds the state, and the App surrounding it is a simple
wrapper.
//---------------Counter.js-------------
import React, { useState } from "react";

const Counter = () => {


const [count, setCount] = useState(0);
return (
<div className="counter">
<h2>Counter</h2>
<div>
<button onClick={() => setCount(count - 1)}>-</button>
<span className="count">{count}</span>
<button onClick={() => setCount(count + 1)}>+</button>
</div>
</div>
);
};

Redux has one global store,


We’ve talked about how Redux keeps the state of your app in a single store; And how you can
extract parts of that state and plug it into your components as props.
You’ll often see the words “state” and “store” used interchangeably. Technically, the state is the
data, and the store is where it’s kept.
So, our first step of refactoring from plain React to Redux, we need to create a store to hold the
state.

createStore:
Redux comes with a handy function that creates stores, and it’s called createStore.
Let’s create our store in the index.js. Import createStore and call it like so:
//----- index.js -------
import React from "react";
import { render } from "react-dom";
import Counter from "./Counter";
import { createStore } from "redux";
import "./index.css";

const store = createStore();

const App = () => (


<div>
<Counter />
</div>
);

render(<App />, document.getElementById("root"));

This shouThe Store Needs a Reducer !


So, here’s the thing about Redux, it’s not very smart.
We might expect that by creating a store, it would give our state a nice default value. Maybe an
empty object?
But Redux makes zero assumptions about the shape of our state. It could be an object, or a number,
or a string, or whatever we need.
In order, to really create our state we need to implement the reducer, which will initiate the state
with the default value.
ld fail with the error “Expected the reducer to be a function.”

Let's provide a reducer


We have to provide a function that will return the state. That function is called a reducer (we’ll see
why in a minute). So let’s make a really simple one, pass it into createStore, and see what happens:
// ----- index.js -------

const reducer = (state, action) => {


console.log('reducer', state, action);
return state;
}

const store = createStore(reducer);


…..

Redux called our reducer at the time we created the store.


Also notice how Redux passed a state, and action, We’ll talk more about actions in a minute. For
now, let’s go over the reducer.
Which function we use to create the store ?
createStore()

Which one is correct?import { createStore } from "redux";


Creating the store is enough to start storing data.False

What is a Redux Reducer?


The term “reducer” might seem a bit scary and foreign, but after this section I think you’ll come to
agree that it is, as the saying goes, “just a function.”
Have you ever used the reduce function on an array?
Here’s how it works: You pass it a function, and it calls your function once for each element of the
array, similar to how map works – you’re probably familiar with map from rendering lists of things
in React.
Your function gets called with two arguments: the last iteration result, and the current array element.
It combines the current item with the previous “total” result and returns the new total.
This will make more sense with an example:
var letters = ["r", "e", "d", "u", "x"];

// `reduce` takes 2 arguments:


// - a function to do the reducing (you might say, a "reducer")

// - an initial value for accumulatedResult

var word = letters.reduce(function(accumulatedResult, arrayItem) {


return accumulatedResult + arrayItem;
}, "");
// <-- notice this empty string argument: it's the initial value

console.log(word); // output => "redux"

Reducer:
Redux reducer is basically a fancy version of Array’s reduce. Earlier, we saw how Redux reducers
have this signature:
(state, action) => newState

Meaning: it takes the current state, and an action, and returns the newState. Looks a lot like the
signature of an Array.reduce reducer!
Redux reducers work just like the function you pass to Array.reduce! The thing they reduce is
actions. They reduce a set of actions (over time) into a single state. The difference is that with array
reduce it happens all at once, and with Redux, it happens over the lifetime of your running app.

Give the Reducer an Initial State:


Remember that the reducer job is to take the current state and an action and return the new state.
It has another job, too: It should return the initial state the first time it’s called. This is sort of like
“bootstrapping” your app. It’s gotta start somewhere, right?
The idiomatic way to do that is to define an initialState variable and use the ES6 default argument
syntax to assign it to state.
Since we’re gonna be moving our Counter state into Redux, let’s set up its initial state right now.
Inside the Counter component our state is represented as an object with a count, so we’ll mirror that
same shape here.
//------index.js--------

const initialState = {
count: 0
};

const reducer = (state = initialState, action) => {


console.log("reducer", state, action);
return state;
};
Let's remember!
If you look at the console, you’ll see it printed {count: 0} as the value for state. That’s what we
want. So that brings us to an important rule about reducers.
Important Rule of Reducers #1: Never return undefined from a reducer.
You always want your state to be defined. A defined state is a happy state. An undefined state is
unhappy (and will likely break your app).
Reducers are the only way to change states in Redux. It is the only place where you can write logic
and calculations. Reducer function will accept the previous state of app and action being
dispatched, calculate the next state and returns the new object

Let's remember what is a Redux Action?


An action is Redux-speak for a plain object with a property called type. That’s pretty much it.
Following those 2 rules, this is an action:
{
type: "add an item",
item: "Apple"
}

This is also an action:


{
type: 7008
}

Here’s another one:


{
type: "INCREMENT"
}

What is an action?
Actions are very free-form things. As long as it’s an object with a type it’s fair game.
In order to keep things sane and maintainable, we Redux users usually give our actions types that
are plain strings, and often uppercased, to signify that they’re meant to be constant values.
An action object describes a change you want to make (like “please increment the counter”) or an
event that happened (like “the request to the server failed with this error”).
Actions, despite their active-sounding name, are boring, inert objects. They don’t really do
anything. Not on their own, anyway.
In order to make an action DO something, you need to dispatch it.

How Redux Dispatch Works?


The store we created earlier has a built-in function called dispatch. Call it with an action, and Redux
will call your reducer with that action (and then replace the state with whatever your reducer
returned).
//-------------index.js-------------
const initialState = {
count: 0
};

const reducer = (state = initialState, action) => {


console.log("reducer", state, action);
return state;
};

const store = createStore(reducer);


store.dispatch({ type: "INCREMENT" });
store.dispatch({ type: "INCREMENT" });
store.dispatch({ type: "DECREMENT" });
store.dispatch({ type: "RESET" });

Add the dispatch:


Add those dispatch calls to your code and check the console.

Every call to dispatch results is a call to your reducer!


Also notice how the state is the same every time? {count: 0} never changes.
That’s because our reducer is not acting on those actions. That’s an easy fix though. Let’s do that
now

Handle Actions in the Redux Reducer:


To make actions actually do something, we need to write some code in the reducer that will inspect
the type of each action and update the state accordingly.
Here’s how we’ll handle the actions. Try this out and take a look at the console.
//----------index.js-------
……..

const reducer = (state = initialState, action) => {


console.log('reducer', state, action);

switch(action.type) {
case 'INCREMENT':
return {
count: state.count + 1
};
case 'DECREMENT':
return {
count: state.count - 1
};
case 'RESET':
return {
count: 0
};
default:
return state;
}
}
………..

The result:

Hey look at that! The count is changing! We’re about ready to hook this up to React
What is a Redux action ?A plain object
What function use to trigger an action in Redux ?dispatch()
An action should always contain a type

How to Use Redux with React?


At this point we have a lovely little store with a reducer that knows how to update the state when it
receives an action. Now it’s time to hook up Redux to React.
To do that, the react-redux library comes with two things:
• a component called Provider,
• a function called connect.
By wrapping the entire app with the Provider component, every component in the app tree will be
able to access the Redux store if it wants to.
In index.js, import the Provider and wrap the contents of App with it. Pass the store as a prop.

What is the function connect()


After this, Counter, and children of Counter, and children of their children, and so on all of them
can now access the Redux store.
But not automatically. We’ll need to use the connect function on our components to access the
store.
Using the connect function that comes with react-redux, you can plug any component into Redux
store and pull out the data it needs.

Connect the component


Previously, we were exporting the component itself. Now we’re wrapping it with this connect
function call, so we’re exporting the connected Counter. As far as the rest of your app is concerned,
this looks like a regular component.

How to Use React Redux connect?


You might notice that the call looks little weird. Why connect(mapStateToProps)(Counter) and not
connect(mapStateToProps, Counter) or connect(Counter, mapStateToProps)? What’s that doing?
It’s written this way because connect is a higher-order function, which is a fancy way of saying it
returns a function when you call it. And then calling that function with a component returns a new
(wrapped) component.
What connect does is hook into Redux, pull out the entire state, and pass it through the
mapStateToProps function that you provide. This needs to be a custom function because only you
know the “shape” of the state you’ve stored in Redux.

Connect the Count Component to Redux:


Prepare the Counter Component for Redux
Right now the Counter has local state. We’re going to rip that out, in preparation to get the count as
a prop from Redux.
import { connect } from "react-redux";

Then we need to “connect” the Counter component to Redux at the bottom:


If we check the console we will find {count: 0 }
It’s our store initial state.
// Add this function:
const mapStateToProps = state => {
console.log(state);
return {
count: state.count
};
};

// Then replace this:


// export default Counter;

// With this:
export default connect(mapStateToProps)(Counter);

Redux provides a standard way to break data updating logic into small reducers. Those reducers
work harmoniously together to complete a complex action.
Dispatch Redux Actions from a React
Component:
By now the counter is connected, we received the count value as a props. The next step is to make
respond to the action ‘INCREMENT’ and ‘DECREMENT’. To make it possible the Redux library
in addition to mapped state, it also passes a function called dispatch to let us trigger the action. If
you check the console you will find that our store state count value change when we dispatch an
action.
const Counter = props => {
console.log(props);
const increment = () => {
props.dispatch({ type: "INCREMENT" });
};

const decrement = () => {


props.dispatch({ type: "DECREMENT" });
};

return (
<div className="counter">
<h2>Counter</h2>
<div>
<button onClick={() => decrement()}>-</button>
<span className="count">{props.count}</span>
<button onClick={() => increment()}>+</button>
</div>
</div>
);
};
const mapStateToProps = state => {
return {
count: state.count
};
};

export default connect(mapStateToProps)(Counter);

Hint : wrapp the entire app with the Provider component import {
Provider
} from "react-redux"; const store =
createStore
(reducer); const App = () => ( <
Provider
store={
store
}> <Counter />
</Provider>
);
Benefits of middleware

What is Middleware?
Redux middlewares work between Action Creators and Reducer. The Middleware intercepts the
action object before Reducer receives it and gives the functionality to perform additional actions or
any enhancements with respect to the action dispatched.

Benefits of middleware
Why use it?
The action/reducer pattern is very clean for updating the state within an application. But what if we
need to communicate with an external API? Or what if we want to log all of the actions that are
dispatched? We need a way to run side effects without disrupting our action/reducer flow.
Middleware allows for side effects to be run without blocking state updates.
We can run side effects (like API requests) in response to a specific action, or in response to every
action that is dispatched (like logging). There can be numerous middleware that an action runs
through before ending in a reducer.
Benefits of middleware
The redux middleware syntax is a mouthful: a middleware function is a function that returns a
function that returns a function.
The first function takes the store as a parameter, the second takes a next function as a
parameter, and the third takes the action dispatched as a parameter.
The store and action parameters are the current redux store and the action dispatched,
respectively. The real magic is the next() function.
The next() function is what you call to say "this middleware is done executing, pass this action to
the next middleware". In other words, middleware can be asynchronous
const reduxMiddleware = store => next => action => {

. . . . . .

next(action);
};
Logging action

Logging: One of the benefits of Redux is that it makes state changes predictable and transparent.
Every time an action is dispatched, the new state is computed and saved. The state cannot change
by itself, it can only change as a consequence of a specific action.
Wouldn't it be nice if we logged every action that happens in the app, together with the state
computed after it? When something goes wrong, we can look back at our log, and figure out which
action corrupted the state.

The logger function:


Middleware is applied in state initialization stage with enhancer applyMiddlware()
import { createStore, applyMiddleware } from "redux";

Logger is function middleware that will log action and state


const logger = store => next => action => {
console.log('dispatching', action)
let result = next(action)
console.log('next state', store.getState())
return result
}

Now only modify the store


const store = createStore(reducer, applyMiddleware(logger));
What’s redux-thunk?
A thunk is another word for a function. But it’s not just any old function. It’s a special (and
uncommon) name for a function that’s returned by another.
function wrapper_function() {
// this one is a "thunk" because it defers work for later:
return function thunk() {
// it can be named, or anonymous
console.log("do stuff now");
};
}

You already know this pattern. You just don’t call it “thunk.” If you want to execute the “do stuff
now” part, you have to call it like wrapper_function()() – calling it twice, basically.

So how does this apply to Redux?


Well, by now, we know that Redux got a few main concepts: there are “actions”, “action creators”,
“reducers”, and “middleware.”
Actions are just objects. As far as Redux is concerned, out of the box actions must be plain objects,
and they must have a type property. Aside from that, they can contain whatever you want – anything
you need to describe the action you want to perform.
Actions look like this:
// 1. plain object
// 2. has a type
// 3. whatever else you want
{
type: "USER_LOGGED_IN",
userName: "dave"
}

Redux thunk:
Since it’s kind of annoying to write those objects by hand all the time (not to mention error-prone),
Redux has the concept of “action creators” to stamp these things out:
function userLoggedIn() {
return {
type: "USER_LOGGED_IN",
username: "dave"
};
}

It’s the same exact action, but now you can “create” it by calling the userLoggedIn function. This
just adds one layer of abstraction.
Instead of writing the action object yourself, you call the function, which returns the object. If you
need to dispatch the same action in multiple places around your app, writing action creators will
make your job easier.

Redux thunk:
Actually redux action does nothing. They are nothing but objects. To make them achieve a concrete
action (Calling an API, trigger another function …) we have to make that code lives inside a
function. This function (also called the thunk) is a bundle of work to be done. Right now our action
creator is performing an action. Like it’s shown in the example below
function getUser() {
return function() {
return fetch("/current_user");
};
}

Redux thunk:
If only there were some way to teach Redux how to deal with functions as actions.
Well, this is exactly what redux-thunk does: it is a middleware that looks at every action that passes
through the system, and if it’s a function, it calls that function. That’s all it does.
The only thing I left out of that little code snippet is that Redux will pass two arguments to thunk
functions:
Dispatch, so that they can dispatch new actions if they need to;
And getState, so they can access the current state.
Here’s an example to illustrate it:
function logOutUser() {
return function(dispatch, getState) {
return axios.post("/logout").then(function() {
// pretend we declared an action creator
// called 'userLoggedOut', and now we can dispatch it
dispatch(userLoggedOut());
});
};
}

the getState function can be useful for deciding whether to fetch new data, or return a cached
result, depending on the current state.

Redux thunk:
Set up redux-thunk in your project
If you have a project that already has Redux set up, adding redux-thunk is two steps.
First, install the package.
npm install --save redux-thunk
Then, wherever you have your Redux setup code, you need to import redux-thunk and insert its
middleware into Redux:
// You probably already import createStore from 'redux'
// You'll need to also import applyMiddleware
import { createStore, applyMiddleware } from "redux";

// Import the `thunk` middleware


import thunk from "redux-thunk";

// Import your existing root reducer here.


// Change this path to fit your setup!
import rootReducer from "./reducers/index";

// The last argument to createStore is the "store enhancer".


// Here we use applyMiddleware to create that based on
// the thunk middleware.
const store = createStore(rootReducer, applyMiddleware(thunk));

Just make sure you wrap thunk in the applyMiddleware call, or it won’t work.
After this, you’re all set: you can now dispatch functions that do whatever you need.
The basic definition of a thunk is that is a function that return another another functionTrue
Can we do an API call from a reducerFalse
To install redux thunk, we need to run:
npm install --save redux-thunk
npm i redux-thunk

Redux with Hooks


When the react release the hooks update, redux follow it and offers a set of hook APIs as an
alternative to the existing connect() Higher Order Component. These APIs allow you to subscribe to
the Redux store and dispatch actions, without having to wrap your components in connect().
These hooks were first added in v7.1.0.

Provider and create createStore


Provider” and “createStore()”: As with connect(), we should start by wrapping our entire
application in a <Provider> component to make the store available throughout the component.
const store = createStore(rootReducer)
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
useSelector()
mapStateToProps and connect argument:
We replace our famous mapStateToProps and connect argument with the selector.This
selector hook : useSelector() allows us to extract data from the Redux store state.

It will be called with the entire state of the Redux store as the only argument.
It will be executed each time the function component is rendered (unless its reference has not
changed since a previous rendering of the component, so that’s result a set of cache can be returned
by the hook without re-executing the selector).
useSelector() also subscribes to the Redux store and runs our selector each time an action is sent.
With mapStateToProps, all individual fields were returned in a combined object. It didn't
matter if the return object was a new reference or not - connect () just compared the individual
fields. With useSelector(), returning a new object every time will always force a re-render by
default. If you want to retrieve multiple values from the store.
When using useSelector with an inline selector, a new instance of the selector is created
whenever the component is rendered.
This works as long as the selector does not maintain any state. However, memoizing selectors (e.g.
created via useSelector() from reselect) have internal state, and therefore care must be taken
when using them.
When the selector does only depend on the state, ensure that it is declared outside of the component
so that the same selector instance is used for each render.

useSelector(): exemple
Example :in the example below we are going to use the createSelector nad useSelector.
import React from "react";
import { useSelector } from "react-redux";
import { createSelector } from "reselect";

const selectNumOfDoneTodos = createSelector(


state => state.todos,
todos => todos.filter(todo => todo.isDone).length
);

export const DoneTodosCounter = () => {


const NumOfDoneTodos = useSelector(selectNumOfDoneTodos);
return <div>{NumOfDoneTodos}</div>;
};

export const App = () => {


return (
<>
<span>Number of done todos:</span>
<DoneTodosCounter />
</>
);
};

useDispatch()
mapDispatchToProps: This function is replaced by “useDispatch” function. This function returns
a reference to the dispatch function from the Redux store. We may use it to dispatch actions as
needed.
import React from "react";
import { useDispatch } from "react-redux";

export const CounterComponent = ({ value }) => {


const dispatch = useDispatch();

return (
<div>
<span>{value}</span>
<button onClick={() => dispatch({ type: "increment-counter" })}>
Increment counter
</button>
</div>
);
};

useCallback()
Pass an inline callback and an array of dependencies. useCallback will return a memoized
version of the callback that only changes if one of the dependencies has changed.
This is useful when passing callbacks to optimized child components that rely on reference equality
to prevent unnecessary renders.
const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
);

Custom context
The <Provider> component allows us to specify an alternate context via the context prop. This is
useful if we’re building a complex reusable component, and we don't want our store to collide with
any Redux store our consumers' applications might use.
To access an alternate context via the hooks API, use the hook creator functions:
import React from "react";
import {
Provider,
createStoreHook,
createDispatchHook,
createSelectorHook
} from "react-redux";
const MyContext = React.createContext(null);

// Export your custom hooks if you wish to use them in other files.
export const useStore = createStoreHook(MyContext);
export const useDispatch = createDispatchHook(MyContext);
export const useSelector = createSelectorHook(MyContext);

const myStore = createStore(rootReducer);

export function MyProvider({ children }) {


return (
<Provider context={MyContext} store={myStore}>
{children}
</Provider>
);
}

You might also like