Using React shouldComponentUpdate with Immutable.js Cursors

I'm having trouble figuring out a short circuit method showing a React component tree branch using Immutable.js cursors.

Take the following example:

import React from 'react'; import Immutable from 'immutable'; import Cursor from 'immutable/contrib/cursor'; let data = Immutable.fromJS({ things: [ {title: '', key: 1}, {title: '', key: 2} ] }); class Thing extends React.Component { shouldComponentUpdate(nextProps) { return this.props.thing.deref() !== nextProps.thing.deref(); } handleChangeTitle(e) { this.props.thing.set('title', e.target.value); } render() { return <div> <input value={this.props.thing.get('title')} onChange={this.handleChangeTitle.bind(this)} /> </div>; } } class Container extends React.Component { render() { const cursor = Cursor.from(this.props.data, 'things', newThings => { data.set('things', newThings); renderContainer(); }); const things = cursor.map(thing => ( <Thing thing={thing} key={thing.get('key')} /> )); return <div> {things} </div>; } } const renderContainer = () => { React.render(<Container data={data} />, document.getElementById('someDiv')); }; 

Say I changed the first Thing header. Only the first Thing will be displayed with a new header and the second Thing will not be re-displayed due to shouldComponentUpdate . However, if I change the second Thing header, the first Thing header will return to '' , since the second Thing cursor still points to an earlier version of the root data.

We update the cursors for each rendering of the Container , but those that do not render due to shouldComponentUpdate also do not get a new cursor with updated root data. The only way I can keep track of cursors is to remove shouldComponentUpdate in the Thing component in this example.

Is there a way to modify this example to use shouldComponentUpdate , using quick reference equality checks, but also update cursors?

Or, if this is not possible, can you provide a general overview of how you usually work with cursors + Respond to components and render only components with updated data?

+5
source share
1 answer

I updated your code, see the comments in the line:

 class Thing extends React.Component { shouldComponentUpdate(nextProps) { return this.props.thing.deref() !== nextProps.thing.deref(); } handleChangeTitle(e) { // trigger method on Container to handle update this.props.onTitleChange(this.props.thing.get('key'), e.target.value); } render() { return <div> <input value={this.props.thing.get('title')} onChange={this.handleChangeTitle.bind(this)} /> </div>; } } class Container extends React.Component { constructor() { super(); this.initCursor(); } initCursor() { // store cursor as instance variable to get access from methods this.cursor = Cursor.from(data, 'things', newThings => { data = data.set('things', newThings); // trigger re-render this.forceUpdate(); }); } render() { const things = this.cursor.map(thing => ( <Thing thing={thing} key={thing.get('key')} onTitleChange={this.onTitleChange.bind(this)} /> )); return <div> {things} </div>; } onTitleChange(key, title){ // update cursor to store changed things this.cursor = this.cursor.update(x => { // update single thing var thing = x.get(key - 1).set('title', title); // return updated things return x.set(key - 1,thing); }); } } const renderContainer = () => { React.render(<Container data={data} />, document.getElementById('someDiv')); }; 
+1
source

All Articles