2

I am trying to use ImmutableJS to help maintain state in a React component. I can use it just fine if the state contains an immutable object. But, if the entire state is an immutable object, then it fails whenever I try to setState() with an error that says

TypeError: this.state.get is not a function.

Below is a minimal example to reproduce the error. Every time the increment button is pushed, the count variable should be incremented and re-rendered. Please help me understand why this approach does not work. Thanks!

import React from 'react';
import { Map as ImmutableMap } from 'immutable'

class App extends React.Component {

  constructor (props) {
    super(props)
    this.state = ImmutableMap({ count: 0 }) // entire state is immutable
  }

  increment () {
    const newCount = this.state.get('count') + 1
    this.setState(prevState => prevState.set('count', newCount))
  }

  render() {
    return (
      <div>
        { this.state.get('count') } // produces error after setState()
        <button onClick={this.increment.bind(this)}>Increment</button>
      </div>
    );
  }

}

export default App;
rdavis
  • 143
  • 1
  • 1
  • 5

1 Answers1

2

See this part of the docs.

When you call setState(), React merges the object you provide into the current state.

So after setState you'll be left with an empty object.

From Immutable.js documentation:

Note that state must be a plain JS object, and not an Immutable collection, because React's setState API expects an object literal and will merge it (Object.assign) with the previous state.

In the current version of the code, the actual merging of the state occcurs in ReactUpdateQueue.js within the getStateFromUpdate function with the following line:

  // Merge the partial state and the previous state.
  return Object.assign({}, prevState, partialState);
ssc
  • 9,528
  • 10
  • 64
  • 94
Ryan Cogswell
  • 75,046
  • 9
  • 218
  • 198