1

I have a component (Which performs text input) rendered twice inside another one.

When I hit a key in one of the text input components, each is notified...

The component takes a time string like "14:30", and should allow hour & minute parts input.

Reflux actions:

let TimeActions = Reflux.createActions([
  'setHour',
  'setMinute'
]);

Reflux mixin:

let TimeMixin = {
  init: function() {
    this.listenToMany(TimeActions);
  },

  onSetHour(h) {
    this.time.hour = h;
    this.trigger(this.time);
  },

  onSetMinute(m) {
    this.time.minute = m;
    this.trigger(this.time);
  }
};

React component:

export default class TimePicker extends React.Component {

  constructor(props) {
    super(props);

    let parts = this.props.time.split(':'),
        time = {
      hour: parts[0],
      minute: parts[1]
    };

    this.store = Reflux.createStore({
      mixins: [ TimeMixin ],
      time: time
    });

    this.state = time;
  }

  componentDidMount() {
    this.unsubscribe = this.store.listen(this.onTimeChanged.bind(this));
  }
  componentWillUnmount() {
    this.unsubscribe();
  }

  onTimeChanged(time) {
console.log('TIME SET TO', time);
    this.setState(time);
  }

  render() {
    let classes = classNames('time-picker');

    return (
      <div className={classes}>
        <table>
          <tbody>
            <tr>
              <td>
                <input type="text" className="hour" maxLength="2"
                       value={this.state.hour}
                       onChange={this.onHourChanged} />
              </td>
              <td class="separator">:</td>
              <td>
                <input type="text" className="minute" maxLength="2"
                       value={this.state.minute}
                       onChange={this.onMinuteChanged} />
              </td>
            </tr>
          </tbody>
        </table>
      </div>
    );
  }

  onHourChanged(event) {
    TimeActions.setHour($(this.getDOMNode()).val());
  }

  onMinuteChanged(event) {
    TimeActions.setMinute($(this.getDOMNode()).val());
  }
}

I render the TimePicker twice from another React component...

...
<TimePicker time={this.props.from} />
<TimePicker time={this.props.to} />
...

... and when typing "01" inside the minute's input of any of the instances, I get the following log:

TIME SET TO Object {hour: "08", minute: "01"}
TIME SET TO Object {hour: "12", minute: "01"}

Any idea of what I am doing wrong?

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
Mike Aski
  • 9,180
  • 4
  • 46
  • 63

1 Answers1

1

This is because you create two stores at the constructor level of your component.

You should create the store outside of the component so only one will exist regardless if you have one or millions instances of your component.

gaelgillard
  • 2,483
  • 1
  • 14
  • 20
  • Ok, I see what you mean. But in this case, any component will share the only store's state. So I will not be able to have differenciated rendering. Am I wrong? – Mike Aski Sep 09 '15 at 08:43
  • 1
    This is where [`shouldComponentUpdate`](https://facebook.github.io/react/docs/component-specs.html#updating-shouldcomponentupdate) will come and help you. – gaelgillard Sep 09 '15 at 08:58
  • Ok. Thx, now I get the idea: I will have to filter the store's items on notification to set each component state according to its proper data set, and `shouldComponentUpdate` will avoid useless rendering. Right? – Mike Aski Sep 09 '15 at 09:04