Basic useContext + useReducer

by Niels Krijger

HTML

<div id="app"></div>

CSS

body {
  background-color: #F2F5F6;
  font-family: sans-serif;
}

button {
  min-width: 3em;
  height: 2em;
  text-align: center;
}

h1 {
  font-size: 2em;
  font-weight: bold;
  padding-bottom: .3em;
}

h2 {
  font-size: 1.5em;
  font-weight: bold;
 
}

div {
  padding: .5em 1em;
}

React

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      return state;
  }
}

const MyContext = React.createContext();

const MyContextProvider = ({ children }) => {
  const [state, dispatch] =  React.useReducer(reducer, { count: 0 });

  return (
    <MyContext.Provider
      value={{ state, dispatch }}
    >
      {children}
    </MyContext.Provider>
  );
};

let buttonIncreaseRenders = 0;

const ButtonIncrement = () => {
  buttonIncreaseRenders += 1;
  const { dispatch } = React.useContext(MyContext);
  
  return (
  	<div className="block">
      <button type="input" onClick={() => dispatch({ type: 'increment' }) }>+ 1</button>
      &nbsp; This button rendered {buttonIncreaseRenders} times
    </div>
  );
}

let buttonDecreaseRenders = 0;

const ButtonDecrement = () => {
  buttonDecreaseRenders += 1;
  const { dispatch } = React.useContext(MyContext);
  
  return (
  	<div className="block">
      <button type="input" onClick={() => dispatch({ type: 'decrement' }) }>- 1</button>
      &nbsp; This button rendered {buttonDecreaseRenders} times
    </div>
  );
}

const StateCount = () => {
  const { state } = React.useContext(MyContext);
  
  return (
  	<div className="block">
  	  <strong>Counter: {state.count}</strong>
  	</div>
  )
};

const App = props => {
	return (
	  <MyContextProvider>
      <h1>Basic useContext + useReducer</h1>
      <StateCount />
      <ButtonIncrement />
      <ButtonDecrement />
    </MyContextProvider>
  );
};

ReactDOM.render(<App />, document.getElementById('app'));