I am using React + Flux. Our team is planning to move from flux to redux. Redux is very confusing for me coming from flux world. In flux control flow is simple from Components -> actions -> Store and store updates back components. Its simple and very clear.
But in redux its confusing. There is no store here, yes there are some examples without using store. I went through several tutorials, it seems everyone has their own style of implementation. Some are using Containers and some are not. (I don't know this Containers concept and not able to understand what mapStateToProps, mapDispatchToProps does).
Can someone clearly explain how control flow happens in redux ?
What are roles of components/containers/actions/action creators/store in redux ?
Difference between redux/react-redux/redux-thunk/any others ??
It would be very helpful if you can post links to any simple and precise redux tutorials.
Can someone clearly explain how control flow happens in redux ?
Redux has (always) a single store.
Whenever you want to replace the state in the store, you dispatch an action.
The action is caught by one or more reducers.
The reducer/s create a new state that combines the old state, and the dispatched action.
The store subscribers are notified that there is a new state.
What are roles of components/containers/actions/action creators/store in redux ?
Store - holds the state, and when a new action arrives runs the dispatch -> middleware -> reducers pipeline, and notifies subscribers when the state is replaced by a new one.
Components - dumb view parts which are not aware of the state directly. Also known as presentational components.
Containers - pieces of the view that are aware of the state using react-redux. Also known as smart components, and higher order components
Note that containers / smart components vs. dumb components is just a good way to structure your app.
Actions - same as flux - command pattern with type and payload.
Action creators - DRY way of creating actions (not strictly necessary)
Difference between redux/react-redux/redux-thunk/any others ?
redux - flux like flow with a single store, that can be used in whatever environment you like including vanilla js, react, angular 1/2, etc...
react-redux - bindings between redux and react. The library offers a set of react hooks - useSelector(), and useStore() to get the data from the store, and useDispatch() to dispatch actions. You can also use the connect() function to create HoCs (higher order components), that listen to the store's state changes, prepare the props for the wrapped component, and re-render the wrapped components when the state changes.
redux-thunk - middleware that allows you to write action creators that return a function instead of an action. The thunk can be used to delay the dispatch of an action, or to dispatch only if a certain condition is met. Used mainly for async calls to api, that dispatch another action on success / failure.
It would be very helpful if you can post links to any simple and
precise redux tutorials.
Redux official docs
Getting Started with Redux
Building React Applications with Idiomatic Redux
Presentational and Container Components
To answer you title question:
What are differences between redux, react-redux, redux-thunk?
redux: main library (independent from React)
redux-thunk: a redux middleware which
helps you with async actions
react-redux: connects your redux store with ReactComponents
redux: Library for managing application state.
react-redux: Library for managing React application (redux) state.
redux-thunk: a middleware for logging, crash reporting, talking to an async API, routing etc...
To my mind, Redux, is still a little confusing for the first time of studying this library, and need some time to understand and start to use one. Even if you use Redux Toolkit - the latest library (from Redux authors) - it also has some tricky moments which might be unclear from the beginning.
I`m using Master-Hook.
Redux , react-redux , redux-thunk , reselect are already installed in the library and you need to follow the steps.
1st step: Create ‘src/hooks.js’ file
import MasterHook from 'master-hook'
export const useMyHook = MasterHook({
storage: "myStorage",
initialState: {
myName: 'Vanda',
},
cache: {
myName: 10000,
}
})
You create your component and export it (useMyHook)
Set the initial State (initialState:...)
Set how long the value need has to stay cached in ms (cache:...)
2nd step: Add Provider to src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import MasterHook from 'master-hook';
ReactDOM.render(
<React.StrictMode>
<MasterHook.Provider>
<App />
</MasterHook.Provider>
</React.StrictMode>,
document.getElementById('root')
);
Import MasterHook
Wrapp your file with MasterHook.Provider
3rd step: Use your hook in src/App.js
import logo from './logo.svg';
import './App.css';
import { useMyHook } from './hooks'
function App() {
const { myName, setMyName } = useMyHook()
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
My name is {myName}
</p>
<a
onClick={() => setMyName('Boris')}
className="App-link"
>
Set my name to 'Boris'
</a>
</header>
</div>
);
}
export default App;
Import your hook
useMyHook
Declare your hook
const { myName, setMyName } = useMyHook()
Use it in your code
{myName}
and
{()=>setMyName('')}
Delete href attribute to prevent it from changing the page. setMyName action is created automatically.
No need to connect to the store. It’s already connected.
4th step: Run your project!
npm run start
That`s it :)
bellow image demonstrates how data flow in redux :
how the data flows through Redux?
Advantages of Redux are listed below:
Predictability of outcome – Since there is always one source of truth, i.e. the store, there is no confusion about how to sync the current state with actions and other parts of the application.
Maintainability – The code becomes easier to maintain with a predictable outcome and strict structure.
Server-side rendering – You just need to pass the store created on the server, to the client-side. This is very useful for initial render and provides a better user experience as it optimizes the application performance.
Developer tools – From actions to state changes, developers can track everything going on in the application in real-time.
Community and ecosystem – Redux has a huge community behind it which makes it even more captivating to use. A large community of talented individuals contribute to the betterment of the library and develop various applications with it.
Ease of testing – Redux’s code is mostly functions which are small, pure and isolated. This makes the code testable and independent.
[Organization][2] – Redux is precise about how code should be organized, this makes the code more consistent and easier when a team works with it.
Related
I'm really new to React and need to ask.
Can I have a ReactJs Redux store in a library and then use that library in an App that also has a Redux store?
Both of them do this:
<Provider store={store}>
..App
</Provider>
I learn ReactJs and am not sure I understand how this is built up how Webpack is loading the code here.
Will these two React Stores collide?
Can they exist independently?
Can they share Reducers? (let's say the App want to use the library Redux store and send a dispatch to it )
I have tested doing some of this but can't make it work. It's like Redux after first loading the library Redux store then it can't load the App store but I'm a novice so must ask
Will these two React Stores collide? / Can they exist independently?
Two different stores created with createStore will not collide, and can exist independently.
behind the scenes, each store instance has a subscribe method, and its own subscribers array.
When using the react-redux Provider component, you are sending an instance of the store down the component tree with React's context API. The instance will be available to all children and decedents of the component which rendered the Provider. If there is another Provider in the way, that Provider's value will override the higher up Provider.
Thus, if you use another Provider with another instance of a store in your library, it will take effect only for the component tree starting from your library component. With the correct composition, there will be no collision.
Can they share Reducers?
Reducers are nothing but pure functions, meaning they shouldn't have any side effects. So you could export and reuse the same reducer logic if you want, you'll just need to register them with every store instance.
Lastly, I disagree with other answers here which claim you shouldn't use multiple stores. You have the exact use case where a separate store would be justified, where you have your main application using one store, and you have a standalone library that uses another unrelated global state.
In my opinion, everything is possible in the programming world, definitely, having a multi-store is possible too.
You asked several questions, first of all, I answer them and then explain a little bit more.
Can I have a Reactjs Redux store in a library and then use that library in an App that also has a Redux store?
Yeah, it's possible, the famous library that makes Redux easy to use is Redux Toolkit, which has a very easy flow to use and implement in your application, even it has a CRA template that you can create your application (zero-config) based on redux npx create-react-app [my-app-name] --template redux or redux-typescript npx create-react-app my-app --template redux-typescript. it works properly.
Will these two React Stores collide?
Can they exist independently?
No, they won't collide because each store (never mind it is redux, mobx, or whatever) has a Provider and you should wrap part of your application or entire of it by using that <Provider store={store}>, so if you wanna have two stores, you can add two Providers and they won't collide. but, in connecting, and getting some data from stores, you should pay attention that which Provider you are going to call from. so they will be able to exist independently.
<ReduxOneProvider store={storeOne}>
<ReduxTwoProvider store={storeTwo}>
<MobxProvider store={mobXStore}>
<App>
</MobxProvider>
</ReduxTWoProvider>
</ReduxOneProvider>
But, totally, I'm not a fan of having multi-store, for more info read here
Can they share Reducers? (let's say the App want to use the library Redux store and send a dispatch to it )
Yes, you know, reducer functions are separate pure functions, located in a folder, when you wanna build your stores, you should gather these functions and combine them, so, the answer is yes, but please consider, the connect function which comes from react-redux want two functions, mapStateToProps and mapDispatchToProps, inside the second you can call a reducer by using dispatch function. so you will have re-render in all stores.
my opinion:
Please avoid having a multi-store, even having one and dealing with it, makes the project a little bit hard to maintain. how you wanna deal with multi. it makes complicated issues.
Yes it is possible.
To keep it simple, library is completely independent package where you can use the redux in normal way. And as you export the library's components to outer world, in same way export the store or dispatch which you would like to use in your application which is consuming the library.
I learned react and Redux at the same time and went "all in" on Redux; basically all state is stored in Redux. And I followed the standard allIds, byId state shape pattern as detailed here.
My app is very data-centric, it talks to an API, and does alot of CRUD type actions - fetchAll, fetchById, add, update, delete.
The API communication is segregated into a "service layer" module that is its own npm package. All calls to this service layer are in the Redux actions, using redux-thunk.
I've realized there is no need to put most everything in Redux, the data is really needed on a specific component, for example. And I would love to simplify this architecture.
So I began to refactor into a custom hook instead. It seemed since my state shape was more of an object rather than scalar, I should use useReducer rather than useState...
// reducer
// -------------------------
const initialState = {
adding: false,
updating: false,
deleting: false,
error: null,
items: null
};
const reducer = (state, action) => {
// implementation omitted for brevity. . .
}
const useItemsApi = () => {
const [state, dispatch] = useReducer(reducer, initialState);
// wrapped in useCallback because called in component's useEffect
const fetchItems = useCallback(async (options) => {
try {
const resp = apiService.fetchItems(options);
} catch (err) {
if(err.status === 401)
// send to login screen
else
dispatch({type: 'error', payload: err});
}
}, [options]);
// addItem, updateItem, deleteItem, etc...
const actions = {fetchItems, updateItem, addItem, deleteItem};
return [state, actions];
};
// component
// -------------------------
const component = (props) => {
const [state, actions] = useItemsApi();
const {fetchItems, updateItem, addItem, deleteItem} = actions;
useEffect(() => {
fetchItems()
}, fetchItems);
// omitted for brevity...
}
When I got to setting the state in the reducer for the update action, I realized it would be easier if I used "allIds" and "byId" pattern.
And at this point I thought - how is this any different than using Redux?
It is going to end up looking like almost the exact same code, and I'm losing some power of selectors, but removing the complexity of redux-thunks. And my current redux actions include specific use case actions (special save for item type X, for ex.) so I'd need to find a place for those.
My question is - is there any reason to refactor this to a hook using local state?
It really boils to three things for me:
Whether you need Redux's middleware, logging features etc or not
How much you care about future stability
Personal taste
Redux offers more than merely state management.
Offloading context handling to Redux is a big plus for me looking forward into the future.
If your application is very data-centric, I would not omit redux-devtools and other middleware (I personally like redux-observable).
When your app grows in complexity you will want to find out about corrupt state updates and state that gets triggered multiple times unexpectedly.
But then again, only you can assess the complexity of your own app and where it will be headed towards in the future.
The rest of this post is 'personal taste', but I'll add it.
Personally I like using Redux for a few different reasons than before mentioned.
I used Redux without using React at all not even so long ago, and also with a framework which nobody probably heard about, which is the Lightning web components framework from Salesforce.
The point being that it keeps state management and view logic in separate libraries.
React becoming a Swiss army knife is something I'm not really in favour of, personally.
React's core strength for me was that it was a view library featuring the virtual DOM with a clear purpose whereas now... well where is the border between it just becoming an opinionated framework?
Using React hooks is not imposed, but then again it sort of is.
If you use React, you will use all of it, this question bringing tribute to this conclusion.
And at this point I thought - how is this any different than using Redux?
So you refactor Redux to the useReducer hook and then wonder, why did I need this?
If you ask then you probably didn't.
Maybe that is just the answer to your question.
Reducer functionality just moved from a state management library to a view library (or is it?). Cool (I guess).
Advantages of storing the state in Redux:
You can access and modify it globally
It persists even after your component is unmounted
Advantages of storing the state in the component:
You can have multiple components with different values in the state, which may be something you want
...Or you could even have multiple hooks of the same type in one component!
You don't need to switch between files. Depending on how your code is organized, Redux can be split into 3 files + 1 file for the component which uses it - while this can help keep your code well-structured for complex use cases, it can be an overkill for keeping track of a simple state. Having to switch between multiple files to work on one component can reduce your productivity (I don't like having to keep track of 4 tabs in my IDE for every feature I work on).
(Also, hooks are new and cool.)
So, use Redux if:
You need to share state between multiple components (or plan to in the future)
You need to keep state even when the component that uses it is unmounted
You might prefer to keep the state in React (hooks or otherwise) in other cases since they simplify your code a bit.
But that doesn't mean you need to refactor your entire codebase. If you think your code is concise enough and you like the way it is organized, or if you are unsure if you will need the state globally in the future, you can keep it in Redux - there is nothing wrong with that!
No, you don't have to.
From my point of view, if only as a state management lib, Redux can be replaced by Hooks (useReducers ect) + local/shared state.
Redux comes before hooks and our app has been implemented by Redux, definitely you don't have the need to replace it.
We can plan to use hooks + shared state as an alternative in our new projects.
I did met with three situations, which are:
Redux ONLY;
Hooks ONLY;
Redux + Hooks;
All of them worked fine.
It's the dilemma that we're in the transition of Redux and Hooks. Hooks are made in a way not to replace redux but it can if you want to.
So in future, you can use any of those, depending on you use case.
Hope it helps.
I am writing an React/Redux application, using TDD. The question is how to approach the first steps in writing a new applications, given all the boilerplate I want to use.
According to TDD, I should write only the minimal code in order to pass my test, and only then refactor. Should I start without Redux, for example, and then refactor and introduce Redux? I will have pretty big refactoring, considering Redux' boilerplate (stores/reducers/wrapper elements etc.)
I understand the huge advantages of the TDD approach. The question is if a better approach will be to be "allowed" to use more than the minimum set of code to pass a test, in those cases..
Redux won't interfere with your ability to write the minimal code to pass each individual test.
Your individual React components are just taking props and doing/displaying something. Your unit tests for those components shouldn't care whether those props are passed in the standard React way, or inserted via react-redux. So the presence of Redux won't affect your ability to pass React component tests with minimal code.
There are some minor exceptions, such as moving component state into Redux state, or changing the way side effects (e.g. fetching data from an API) are handled. Those types of changes may require some changes to your tests, but they will likely make them simpler, if anything.
Of course if you add Redux, you will have to write tests for the new Redux reducers/action creators/selectors, etc., but writing those tests is super straight-forward. You're not going to be duplicating any work: the amount of time you spend writing tests will be about the same regardless of whether you start with or without Redux.
As for the general concept of starting with or without Redux: Dan Abramov, who created Redux, recommends starting with plain React and then only adding Redux down the road if you find that you need it.
My preferred way is to test react first and check if the component correctly renders based on the props fed to it.
something like this:
import {App} from '../../src/containers/App';
import React from 'react';
import ReactDOM from 'react-dom';
import {
renderIntoDocument,
scryRenderedDOMComponentsWithTag
} from 'react-addons-test-utils';
import {expect} from 'chai';
describe('Main page',() => {
it('should show a sign-in page if isAuthenticated is false',() => {
const component = renderIntoDocument(
<App isAuthenticated={false}/>
);
const buttons = scryRenderedDOMComponentsWithTag(component,'button')
expect(buttons.length).to.be.equal(1)
});
it('should show a welcome text if isAuthenticated is true',() => {
const component = renderIntoDocument(
<App isAuthenticated={true}/>
);
const text = scryRenderedDOMComponentsWithTag(component,'h1')
expect(text).to.have.string('welcome')
})
})
i would then add tests for redux to check if the state changes based on the input provided to the reducers.
its a matter of preference in the end.
I'm currently learning React and I am trying to figure out how to use it with Redux for building a mobile app. I'm kind of confused on how the two are related/usable together. For example, I completed this tutorial in React https://www.raywenderlich.com/99473/introducing-react-native-building-apps-javascript, but now I want to play around with adding some reducers/actions to that app and I am not sure where those would tie in with what I've already done.
React is a UI framework that takes care of updating the UI in response to the “source of truth” that is usually described as a state “owned” by some component. Thinking in React describes the React state ownership concept very well, and I strongly suggest you go through it.
This state ownership model works well when the state is hierarchical and more or less matches the component structure. This way the state gets “spread out” across many components, and the app is easy to understand.
However sometimes distant parts of the app want to have access to the same state, for example, if you cache fetched data and want to consistently update it everywhere at the same time. In this case, if you follow the React model, you’ll end up with a bunch of very large components at the top of the component tree that pass a myriad of props down through some intermediate components that don’t use them, just to reach a few leaf components that actually care about that data.
When you find yourself in this situation, you can (but don’t have to) use Redux to “extract” this state management logic from the top-level components into separate functions called “reducers”, and “connect” the leaf components that care about that state directly to it instead of passing the props through the whole app. If you don’t have this problem yet, you probably don’t need Redux.
Finally, note that Redux is not a definitive solution to this problem. There are many other ways to manage your local state outside the React components—for example, some people who didn’t like Redux are happy with MobX. I would suggest you to first get a firm understanding of React state model, and then evaluate different solutions independently, and build small apps with them to get a sense of their strengths and weaknesses.
(This answer is inspired by Pete Hunt’s react-howto guide, I suggest you to read it as well.)
I've found that the ideal path for adding Redux to an application/stack is to wait until after you/app/team are feeling the pains that it solves. Once you start seeing long chains of props building up and being passed down through multiple levels of components or your finding yourself orchestrating complex state manipulations/reads, that could be a sign that your app may benefit from introducing Redux et al.
I recommend taking an app that you've already built with "just React" and see how Redux might fit into it. See if you can gracefully introduce it by plucking out one piece of state or set of "actions" at a time. Refactor towards it, without getting hung up on a big bang rewrite of your app. If you're still having trouble seeing where it might add value, then that could be a sign that your app is either not large or complex enough to merit something like Redux on top of React.
If you haven't come across it yet, Dan (answered above) has a great short-video series that walks through Redux on a more fundamental level. I highly suggest spending some time absorbing pieces of it: https://egghead.io/series/getting-started-with-redux
Redux also has some pretty great docs. Especially explaining a lot of the "why" such as http://redux.js.org/docs/introduction/ThreePrinciples.html
I have prepared this document to understand Redux. Hope this clears your doubt.
-------------------------- REDUX TUTORIAL ----------------------
ACTIONS-
Actions are payloads of information that send data from your application to the store. They are the only source of information from the store. You can send them
only using store.dispatch().
Example-
const ADD_TODO = 'ADD_TODO'
{
type:ADD_TODO,
text: 'Build my first redux app'
}
Actions are plain javascript object. Action must have a [ type ] property that indicates the type of action being performed. The type should be defined as a string constant.
ACTION CREAToRS-----
---------------- ---- Action creators are exactly the function that creates action
It is easy to conflate the terms - action and action creator.
In redux action, creator returns an action.
function addToDo(text) {
return {
type: ADD_TODO,
text
}
}
to initialte dispatch pass the result to the dispatch() function.
dispatch(addToDo(text));
dispatch(completeToDo(index))
Alternatively, you can create a bound action creator that automatically dispatches.
cosnt boundAddTodO = text => dispatch(addToDo(text));
now you can directly called it
boundaddTodO(text);
The dispatch() functionn can be directly accessed from store.dispatch(). but we
access it using a helper connect() method.
Actions.js.....................
Actions...........
exports cosnt ADD_TODO = 'ADD_TODO';
exports cosnt TOGGLE_TODO = 'TOGGLE_TODO'
Actions Creators
export function addToDO(text){
return {
type: ADD_TODO,
text
}
}
.........................REDUCERS..................................
Reducers specify how the applications state changes in response to actions sent to the store.
Designing the state shap
In redux all the application state is store in single object. You have to store some data as well as some state.
{
visibilityFilter: 'SHOW_ALL',
todos: [
{
text: 'Consider using redux',
completed: true
},
{
text: 'Kepp all the state in single tree'
}
]
}
Handling Actions
---------------- the reducers are the pure functions that take the previous state and action, and return a new state.
(previousState, action) => newState
We will start by specifying the initial state. Redux will call our reducers with an undefined state for the first time. this is our chance to return the state of our app.
import { visiblilityFilters } from './actions';
const initialState = {
visibilityFilter: VisibilityFilters.SHOW_ALL,
todo: []
}
function todoApp(state, action){
if(typeof state == 'undefined'){
return initialState;
}
// dont handle other cases as of now.
return state;
}
you can do the same using ES6 way of handling the JS
function todoApp(state = initialState, action) {
switch (action.type) {
case SET_VISIBILITY_FILTER:
return Object.assign({}, state, {
visibilityFilter: action.filter
})
default:
return state
}
}
................................. STORE...................................
The store is a object that brings them together. the store has following responsbility
hold application state
allow access to state via getState()
Allow state to be updated via dispatch()
Register listerneres via suscriber(listener)
Note. use combineReducers() to combine several reducers into one.
const store = createStore(todoapp); // the todoapp are the reducers
This is how redux works. A action is dispatched from any compoenent or view. Action MUST have "type" property and may be any property which holds information of action happened. The data passed in action, could be relevant to different reducer, so same object get passed to different reducer. Each reducer takes/ make-out its part/contribution to state. The output is then merged and new state get formed, and the component which must be subscribed for state change event gets notified.
In above example, brown color has all 3 component RGB. Each reducer receives same brown color and they seperate out its contribution to the color.
Firstly, you don't need to add Redux to your application if you don't need it! Simple, so don't force yourself to include it in your project if you don't need it at all! But that doesn't mean Redux is no good, it's really helpful in large applications, so read on ...
Redux is a state management for your React application, think about Redux like a local store which track of your state as you go, you can access the state in any page and route you want, also compare to Flux, you only have one store, means one source of truth...
Look at this image to understand what Redux does first at a glance:
Also this's how Redux introduce itself:
Redux is a predictable state container for JavaScript apps.
It helps you write applications that behave consistently, run in
different environments (client, server, and native), and are easy to
test. On top of that, it provides a great developer experience, such
as live code editing combined with a time traveling debugger.
You can use Redux together with React, or with any other view library.
It is tiny (2kB, including dependencies).
Also as per documentation, there are Three Principles for Redux as below:
1. Single source of truth
2. State is read-only
3. Changes are made with pure functions
So basically when you need to a single store to keep track of anything you like in your application, then Redux is handy, you can access it anywhere in your app, in any route... simply using store.getState();
Also using the middleware Redux, you can do manage the state much better, there a list of handy components and middleware on official page of Redux!
Simply if your application gonna be big, with many components, states and routing try to implements Redux from start! It will help you on the way for sure!
When we write application we need to manage state of the application.
The React manages states locally within the component if we need to share the states between components we can use props or callbacks.
But as application grows it becomes difficult to manage states and state transformations.State and state transformations need to properly tracked in order to debug the applications.
Redux is a predictable state container for JavaScript apps that manages state and state transformations and is often used with React,
The concept of redux can be explained in following image.
When user triggers an action when user interact with the component and an action is dispatched to store then the reducer in the store accepts the action and update the state of the application and stored in the application wide immutable global variable when there is an update in store the corresponding view component subscribed to the state will get updated.
Since state is managed globally and with redux it is easier to maintain.
Having used Redux and personally finding it cumbersome, I found passing around an object to my components as a prop can be a much easier way to maintain state. Not to mention it's an easy way of making references to functions to call in other components. It can solve a lot of the cumbersome issues of passing messages between components in React, so it's a two for one.
I normally post code related stuff on Stack, but this is more a question about what the general thoughts of the community are.
There seems to be a lot of people advocating the use Redux with React to manage data/state, but while reading and learning both I've come across something that doesn't quite look right.
Redux
At the bottom of this page: http://redux.js.org/docs/basics/UsageWithReact.html (Passing the Store) it recommends using the "Magic" of React 'Context'.
One option would be to pass it as a prop to every container component. However it gets tedious, as you have to wire store even through presentational components just because they happen to render a container deep in the component tree.
The option we recommend is to use a special React Redux component called to magically make the store available to all container components...
React
On the React Context page (https://facebook.github.io/react/docs/context.html) it has a warning at the top:
Context is an advanced and experimental feature. The API is likely to change in future releases.
Then at the bottom:
Just as global variables are best avoided when writing clear code, you should avoid using context in most cases...
Do not use context to pass your model data through components. Threading your data through the tree explicitly is much easier to understand...
So...
Redux recommends using the React 'Context' feature rather than passing the store along down to each component via 'props'. While React recommends the opposite.
Also, it seems that Dan Abramov (the creator of Redux) now works for Facebook (the creator of React), just to confuse me more.
Am I reading all this right..?
What is the general current consensus on this issue..?
Context is an advanced feature and is subject to change. In some cases its conveniences outweigh its downsides so some libraries like React Redux and React Router choose to rely on it despite the experimental nature.
The important part here is the word libraries. If context changes its behavior, we as library authors will need to adjust. However, as long as the library doesn’t ask you to directly use the context API, you as the user shouldn’t have to worry about changes to it.
React Redux uses context internally but it doesn’t expose this fact in the public API. So you should feel much safer using context via React Redux than directly because if it changes, the burden of updating the code will be on React Redux and not you.
Ultimately React Redux still supports always passing store as a prop so if you want to completely avoid context, you have that choice. However I would say this is impractical.
TLDR: Avoid using context directly unless you really know what you are doing. Using a library that happens to rely on context internally is relatively safe.
I don't know about others, but I prefer using react-redux's connect decorator to wrap my components so that only the props from the store I need are passed into my component. This justifies the use of context in a sense because I am not consuming it (and I know, as a rule, any code that I am in charge of will not consume it).
When I test my components, I test the non-wrapped component. Because react-redux only passed the props I needed on that component, I now know exactly what props I need when I'm writing the tests.
I suppose the point is, I don't ever see the word context in my code, I don't consume it, so to a certain degree, it doesn't affect me! This doesn't say anything about Facebook's "experimental" warning.. If context disappeared, I'd be just as screwed as everyone else until Redux was updated.
There's an npm module that makes it really easy to add redux to the react context
https://github.com/jamrizzi/redux-context-provider
https://www.npmjs.com/package/redux-context-provider
import React, { Component } from 'react';
import ReduxContextProvider from 'redux-context-provider';
import createStore from './createStore';
import actions from './actions';
import Routes from './routes';
export default class App extends Component {
render() {
return (
<ReduxContextProvider store={store} actions={actions}>
<Routes />
</ReduxContextProvider>
);
}
}
React ships with all the features you need to handle your state without a single additional library. Most of your application's states should not be global as they live just fine in a useState or useReducer or custom hook next to your components.
So before you dive into the world of advanced state management (e.g. Redux), consider using the tools React ships with out of the box.
If you are interested in learning a bit more about this, I'd recommend this article by Andy Fernandez, which dives into the details on Redux: Context API vs Redux