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

Using Redux with React

Using Redux with React

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