0.1.0 • Published 6 years ago

react-redux-setstate v0.1.0

Weekly downloads
3
License
MIT
Repository
github
Last release
6 years ago

react-redux-setstate

A HOC that overrides the React setState API to use Redux for storing component state.

This library allows you to use React's familiar this.state and this.setState API for controlling state on a component, while leveraging Redux's global store for managing application state.

One of Redux's key features is that state is not localized, meaning that it encourages reuse of application-wide state over redundancy of data. However, there are certainly times when your state is truly local to a component: for example, when a confirmation modal is open, or an expandable menu is toggled. In these instances, using Redux to manage state means a lot of headache in wiring components up to the store and setting up single-use action creators and reducers, as well as ensuring that collisions in the store namespace are avoided.

In these cases, it's often better to just use React's built-in state API, since it is properly isolated to the particular component instance. However, this has some major drawbacks:

  • React component state is lost when hot-reloading
  • React component state is lost if the component is unmounted
  • The entire application state tree is not properly represented in Redux, meaning that restoring the state from localStorage or loading production state into a local environment to reproduce a bug is difficult

This library seeks to bridge the gap between the ease-of-use of React's state API with the power of Redux to completely manage application state. It accomplishes this by overriding the state getters and setters and the setState method on a class component via a decorator. You can use the React API you're already familiar with, and you will automatically leverage your Redux store.

Installation

npm install react-redux-setstate

Usage

Add the reducer to your combineReducers call, using the key componentState:

import { reducer as componentState } from 'react-redux-setstate'

export default combineReducers({
  // ... your other reducers
  componentState,
})

Then, decorate your stateful component with the connectComponentState function:

import React, { Component } from 'react'
import { connectComponentState } from 'react-redux-setstate'

class MyComponent extends Component {
  constructor(props) {
    super(props)
    this.state = {
      count: 0
    }
  }

  increment = () => {
    this.setState({ count: this.state.count + 1 })
  }

  render() {
    return (
      <div>
        {this.state.count}
        <button onClick={this.increment}>+</button>
      </div>
    )
  }
}

export default connectComponentState()(MyComponent)

The component's state will be stored in the componentState namespace in the Redux store, rather than in React's internal state manager.

Because the component can be rendered multiple times, the default behavior of react-redux-setstate is to generate a random identifier in the store for every instance of the component that is rendered, via a UUID. This is not ideal, since remounting the component (via an unmount/remount, state restoration, or hot-reload event) will generate a new ID.

Instead, you should pass a function into the decorator. The function will receive the component's props and must return a unique identifier for the component. Assuming this identifier is pure, deterministic, and will not collide, you can use this to restore state on the component from the store when it is remounted.

const getComponentKey = props => `MyComponent__${props.id}`

export default connectComponentState(getComponentKey)(MyComponent)

Remember, this identifier must be globally unique across the app, for any and all instances of components that use react-redux-setstate. This may require passing additional props down to the component to guarantee its uniqueness. Of course, if your component is a singleton, you can just have this function return a constant string.

Limitations

This project is in early development. Here are some known limitations:

  • The React setState method also accepts a function to update the state, which is guaranteed to be applied with the latest state, which helps with managing concurrency. This is not implemented yet in this project.
  • The React setState method accepts a callback as the second argument, which is called when the state is actually updated and reflected in the state object. This is not implemented yet in this project.
  • Remember, Redux's state must be made up of plain, serializable data, whereas React state is in-memory and can include instances of other objects, like DOM elements or Dates. When using this library, make sure your component state is only primitive values, plain objects, and arrays.
0.1.0

6 years ago