Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Using Redux with React

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

Using Redux with React

Avatar for Jussi Pohjolainen

Jussi Pohjolainen

November 07, 2020
Tweet

More Decks by Jussi Pohjolainen

Other Decks in Technology

Transcript

  1. Redux: Motivation • Avoid prop-drilling, passing props between components can

    be a pain, if several components • A -> B -> C -> D • B and C only are here passing data, they do not do anything to it, only D wants the data. • Passing data between siblings is a pain also • Pull data up into parent component and pass it down with props
  2. Redux to rescue • Redux gives you one global "parent"

    where you store your data • Connect sibling components to the data with Redux • On source of "truth", components can ask data from the redux store
  3. Redux alternative • Redux uses Context API to pass data

    around • It is possible to use Context API directly but you will miss out some of Redux nice features • If your app is really simple and you want to pass data around, Context API might be good for you • useContext, useReducer hooks
  4. Install • Redux: • Gives you store, lets you keep

    state in it, get state out and respond to state changes. Knows nothing about React! • React redux • Connect pieces of the state to react components • To install • npm install redux react-redux
  5. Redux has one Global Store import { createStore } from

    'redux'; const store = createStore(); Will fail: Error: Expected the reducer to be a function.
  6. Using reducer import { createStore } from 'redux'; function reducer(state,

    action) { console.log('reducer', state, action); return state; } const store = createStore(reducer); current state and an action. Returns new state
  7. Initial state import { createStore } from 'redux'; function reducer(state

    = { count: 0 }, action) { console.log('reducer', state, action); return state; } const store = createStore(reducer); Setting initial state
  8. Example import { createStore } from 'redux'; function reducer(state =

    { count: 0 }, action) { console.log('reducer', state, action); return state; } const store = createStore(reducer); store.dispatch({ type: "INCREMENT" }); Dispatching action!
  9. import { createStore } from 'redux'; function reducer(state = {

    count: 0 }, action) { console.log('reducer', state, action); switch(action.type) { case 'INCREMENT': return { count: state.count + 1 }; case 'DECREMENT': return { count: state.count - 1 }; default: return state; } } const store = createStore(reducer); store.dispatch({ type: "INCREMENT" }); store.dispatch({ type: "DECREMENT" }); store.dispatch({ type: "INCREMENT" }); Act on actions state is read only, do NOT modify return new state
  10. import { createStore } from 'redux'; function reducer(state = {

    count: 0 }, action) { console.log('reducer', state, action); switch(action.type) { case 'INCREMENT': return { count: state.count + 1 }; case 'DECREMENT': return { count: state.count - 1 }; default: return state; } } const store = createStore(reducer); store.dispatch({ type: "INCREMENT" }); store.dispatch({ type: "DECREMENT" }); store.dispatch({ type: "INCREMENT" }); Act on actions state is read only, do NOT modify return new state
  11. Subscribing to Store let { createStore } = require("redux"); function

    reducer(state = { count: 0 }, action) { switch (action.type) { case "INCREMENT": return { count: state.count + 1 }; case "DECREMENT": return { count: state.count - 1 }; default: return state; } } const store = createStore(reducer); store.subscribe(() => console.log(store.getState()));
  12. React + Redux const App = () => ( <Provider

    store={store}> <Counter/> </Provider> ) Every component will have access to store (connect first)
  13. Local State: not using redux function Counter() { let [counter,

    setCounter] = React.useState(0) return <div> <h1>Counter</h1> <button onClick={ () => setCounter(counter + 1) }>+</button> {counter} <button onClick={ () => setCounter(counter - 1) }>-</button> </div> }
  14. Removal of local state and use props function Counter(props) {

    console.log(props) // {} // let [counter, setCounter] = React.useState(0) return <div> <h1>Counter</h1> <button onClick={ () => null }>+</button> {props.count} <button onClick={ () => null }>-</button> </div> } Using props, it's empty
  15. Connecting to redux import { connect } from 'react-redux'; function

    mapStateToProps(state) { return { count: state.count }; } function Counter(props) { console.log(props) // {count: 1} return <div> <h1>Counter</h1> <button onClick={() => null}>+</button> {props.count} <button onClick={() => null}>-</button> </div> } export default connect(mapStateToProps)(Counter) Returning connected component! Uses a custom function to map universal state to props Function that gets the universal state and transforms it to props Props is now available!
  16. Dispatch import { connect } from 'react-redux'; function mapStateToProps(state) {

    return { count: state.count }; } function Counter(props) { console.log(props) // {count: 1} return <div> <h1>Counter</h1> <button onClick={() => props.dispatch({ type: "INCREMENT" }) }>+</button> {props.count} <button onClick={() => props.dispatch({ type: "DECREMENT" }) }>-</button> </div> } export default connect(mapStateToProps)(Counter) https://daveceddia.com/redux-tutorial/ https://www.valentinog.com/blog/redux/#react-redux-tutorial-getting-to-know-redux-reducers Props is filled also with dispatch function!
  17. Providing Store import store from "./Store.js"; import { Provider }

    from "react-redux"; ReactDOM.render( <React.StrictMode> <Provider store={store}> <App /> </Provider> </React.StrictMode>, document.getElementById("root") );
  18. Store import { createStore } from "redux"; function reducer(state =

    { count: 0 }, action) { switch (action.type) { case "INCREMENT": return { count: state.count + 1 }; case "DECREMENT": return { count: state.count - 1 }; default: return state; } } const store = createStore(reducer); export default store;
  19. IncrementDecrement import { connect } from "react-redux"; function IncrementDecrement(props) {

    const add = () => { props.dispatch({ type: "INCREMENT" }); }; const remove = () => { props.dispatch({ type: "DECREMENT" }); }; return ( <div> <button onClick={add}>+</button> <button onClick={remove}>-</button> </div> ); } export default connect()(IncrementDecrement);
  20. DisplayCount import { connect } from "react-redux"; function mapStateToProps(state) {

    return { id: state.count, }; } function DisplayCount(props) { return <div>count = {props.id}</div>; } export default connect(mapStateToProps)(DisplayCount);