React

Install

npm install overmind overmind-react

There are two different ways to connect Overmind to React. You can either use a traditional Higher Order Component or you can use the new hooks api to expose state and actions.

When you connect Overmind to a component you ensure that whenever any tracked state changes, only components interested in that state will re-render, and will do so “at their location in the component tree”. That means we remove a lot of unnecessary work from React. There is no reason for the whole React component tree to re-render when only one component is interested in a change.

Hook

// overmind/index.js
import {
  createStateHook,
  createActionsHook,
  createEffectsHook,
  createReactionHook
} from 'overmind-react'
import { state } from './state'
import * as actions from './actions'

export const config = {
  state,
  actions
}

export const useState = createStateHook()
export const useActions = createActionsHook()
export const useEffects = createEffectsHook()
export const useReaction = createReactionHook()

// index.js
import * as React from 'react'
import { render } from 'react-dom'
import { createOvermind } from 'overmind'
import { Provider } from 'overmind-react'
import { config } from './overmind'
import App from './components/App'

const overmind = createOvermind(config)

render((
  <Provider value={overmind}>
    <App />
  </Provider>
), document.querySelector('#app'))

// components/App.jsx
import * as React from 'react'
import { useState, useActions, useEffects, useReaction } from '../overmind'

const App = () => {
  // General
  const state = useState()
  const actions = useActions()
  const effects = useEffects()
  const reaction = useReaction()
  // Or be specific
  const { isLoggedIn } = useState().auth
  const { login, logout } = useActions().auth

  return <div />
}

export default App

The benefit of using specific hooks is that if you only need actions in a component, you do not add tracking behaviour to the component by using useActions. Also it reduces the amount of destructuring needed, as you can point to a namespace on the hook.

Rendering

When you use the Overmind hook it will ensure that the component will render when any tracked state changes. It will not do anything related to the props passed to the component. That means whenever the parent renders, this component renders as well. You will need to wrap your component with REACT.MEMO to optimize rendering caused by a parent.

Passing state as props

If you pass a state object or array as a property to a child component you will also in the child component need to use the useState hook to ensure that it is tracked within that component, even though you do not access any state or actions. The devtools will help you identify where any components are left “unconnected”.

// components/Todos.jsx
import * as React from 'react'
import { useState } from '../overmind'
import Todo from './Todo'

const Todos = () => {
  const state = useState()

  return (
    <ul>
      {state.todos.map(todo => <Todo key={todo.id} todo={todo} />)}
    </ul<
  )
}

export default Todos

// components/Todo.jsx
import * as React from 'react'
import { useState } from '../overmind'

const Todo = ({ todo }) => {
  useState()

  return <li>{todo.title}</li>
}

export default Todo