Provider
Why do we need to wrap all our components inside Provider
?
connect
:How is connect
passing redux store as props
to components ?
Provider
and connect
?Below is a fully working simple React Redux example that just displays a name from the redux store and uses React Redux connect
and Provider
, so how ConnectedComponent
can simply access this.props.name
?
import React, { Component } from "react"; import { render } from "react-dom"; import { createStore } from "redux"; import { Provider, connect } from "react-redux"; var defaultState = { name: "Amr" }; function rootReducer(state = defaultState, action) { return state; } var store = createStore(rootReducer); class ConnectedComp extends Component { render() { return ( <h2>{this.props.name}</h2> ); } } function mapStateToProps(state) { return { name: state.name }; } ConnectedComp = connect(mapStateToProps)(ConnectedComp); class App extends Component { render() { return ( <Provider store={store}> <ConnectedComp /> </Provider> ); } } render(<App />, document.getElementById("root"));
A fully working example here https://codesandbox.io/s/lpvnxro7n7
Provider. Every Context object comes with a Provider React component that allows consuming components to subscribe to context changes. The Provider component accepts a value prop to be passed to consuming components that are descendants of this Provider. One Provider can be connected to many consumers.
Provider is the container for all React Spectrum applications. It defines the theme, locale, and other application level settings, and can also be used to provide common properties to a group of components.
Overview The <Provider> component makes the Redux store available to any nested components that need to access the Redux store. Since any React component in a React Redux app can be connected to the store, most applications will render a <Provider> at the top level, with the entire app's component tree inside of it.
mapStateToProps is a function that you would use to provide the store data to your component, whereas mapDispatchToProps is something that you will use to provide the action creators as props to your component.
To be able to understand how Provider
and connect
work we need to understand 2 concepts in React
Context is a way to pass data through the component tree without having to pass the props down manually at every level, you can learn more about context here
A higher-order component is a function that takes a component and returns a new component but before returning the new component you can pass extra custom props and then return it, you can learn more about HOC here
Provider
and connect
Now that we understand both Context and Higher Order Component, we will use them to create the same fully working example in the question but using our own built myProvider
and myConnect
MyProvider
//This is how we utilize React Context and create MyProvider component that will pass store to all its child components automatically //This is also known by Provider pattern class MyProvider extends Component { //By adding the getChildContext function and childContextTypes, React passes the information down automatically to any component in the subtree getChildContext() { const { store } = this.props return { store } } render() { return this.props.children; } } MyProvider.childContextTypes = { store: PropTypes.object.isRequired, }
myConnect
//This is the Higher Order Component function myConnect(mapStateToPropsFunc) { return function (WrappedComp) { var myHOC = class HOC extends Component { render() { //Now we access redux store using react context api as it will be passed by MyProvider automatically to all child components var myStore = this.context.store.getState(); //mapStateToPropsFunc is just used to structure the props required by the component so we pass to mapStateToPropsFunc the whole store and then it returns a mapped object with required props thats why it is well known by mapStateToProps var storeToBePassed = mapStateToPropsFunc(myStore); return ( //We pass the result from executing mapStateToPropsFunc to the wrapped component and this is how the components get passed props from redux store <WrappedComp {...storeToBePassed} /> ) } } //We need to define contextTypes otherwise context will be empty myHOC.contextTypes = { store: PropTypes.object }; //return new component that has access to redux store as props mapped using mapStateToProps function return myHOC; } }
MyProvider
and myConnect
//Note that we removed react-redux library import React, { Component, Children } from "react"; import { PropTypes } from "prop-types"; import { render } from "react-dom"; import { createStore } from "redux"; var defaultState = { name: "Amr" }; function rootReducer(state = defaultState, action) { return state; } var store = createStore(rootReducer); class App extends Component { render() { //Here we use our own built myProvider and pass store return ( <MyProvider store={store}> <ConnectedComp /> </MyProvider> ); } } class ConnectedComp extends Component { render() { return ( <h2>{this.props.name}</h2> ); } } //mapStateToProps is a normal function that get store as parameter and return the required props by that component, btw this function can have any name function mapStateToProps(state) { return { name: state.name }; } //Here we use our own built myConnect ConnectedComp = myConnect(mapStateToProps)(ConnectedComp); render(<App />, document.getElementById("root"));
You can test the above implementation here https://codesandbox.io/s/727pl0mqoq
This example is a simple illustration of how react-redux Provider
and connect
can be built by utilizing both React Context
and HOC
.
This give us a better understanding of why we use Provider
, connect
and mapStateToProps
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With