最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Member variables in react class are "shared" by reference - Stack Overflow

programmeradmin5浏览0评论

When i create several instances of a react class (by using React.createElement on the same class), some member variables are shared between the instances (arrays and objects are shared, strings and booleans etc. not).

For me this feels horrible and scary and wrong. Is this a bug or is there another way to do what i want to do?

Please have a look: ,js,console,output

When i create several instances of a react class (by using React.createElement on the same class), some member variables are shared between the instances (arrays and objects are shared, strings and booleans etc. not).

For me this feels horrible and scary and wrong. Is this a bug or is there another way to do what i want to do?

Please have a look: http://jsbin./kanayiguxu/1/edit?html,js,console,output

Share Improve this question edited Apr 21, 2015 at 22:20 tbodt 17k7 gold badges61 silver badges86 bronze badges asked Apr 17, 2015 at 10:55 delijahdelijah 832 gold badges3 silver badges7 bronze badges 4
  • 2 "Questions seeking debugging help ("why isn't this code working?") must include the desired behavior, a specific problem or error and the shortest code necessary to reproduce it in the question itself. Questions without a clear problem statement are not useful to other readers. See: How to create a Minimal, Complete, and Verifiable example." – T.J. Crowder Commented Apr 17, 2015 at 10:57
  • I suggest you post the (relevant) parts of the code on SO, and you might also want to check out JavaScript docs on scope in JavaScript: smashingmagazine./2009/08/01/… – Ted Nyberg Commented Apr 17, 2015 at 10:58
  • 1 @TedNyberg: From the description, this has nothing to do with scope. It has to do with the difference between primitives and object references on prototypes, most likely. – T.J. Crowder Commented Apr 17, 2015 at 10:59
  • @T.J.Crowder That sounds about right. Could remend the following link to the OP: stackoverflow./questions/518000/… – Ted Nyberg Commented Apr 17, 2015 at 11:05
Add a ment  | 

1 Answer 1

Reset to default 12

What you should be doing is setting state on your ponent, instead of having state as arbitrary properties on your React ponent.

So instead of doing this:

var MyComponent = React.createClass({
  myArray: [1, 2, 3],
  ponentWillMount() {
    this.myArray.push(this.myArray.length + 1);
  },
  render() {
    return (
      <span>{this.myArray.length}</span>
    );
  }
});

You should be doing this:

var MyComponent = React.createClass({
  getInitialState() {
    return {
      myArray: [1, 2, 3]
    };
  },
  ponentWillMount() {
    this.setState(state => {
      state.myArray.push(state.myArray.length + 1);
      return state;
    });
  },
  render() {
    return (
      <span>{this.myArray.length}</span>
    );
  }
});

The reason being that all of a ponents state and data should reside in this.state and this.props which is controlled and handled by React.

The benefit you get from using props and state for this, is that React will know when those change, and from that it can tell when it's time to re-render your ponent. If you store state as arbitrary properties or globals, React won't know when those change, and cannot re-render for you.

The reason for the behaviour you're seeing is that every instance of the ponent uses the object you give to React.createClass() as its prototype. So all instances of the ponent has a myArray property, but that is on the prototype chain, and thus shared by all instances.

If you truly want something like this and you want to avoid this.state, you should use something like ponentWillMount and inside that method, assign properties to this. This will make sure that such data is only on that particular instance, and not on the prototype chain.

EDIT

To even further clearify, it can be good to know that the object passed to React.createClass() isn't the actual object on the prototype. What React does is that it iterates over all properties on that object, and copies them onto the prototype of the React element object. This can be illustrated by this example:

var obj = {
  myArray: [1, 2, 3],
  title: 'My title',
  ponentWillMount() {
    this.myArray.push(this.myArray.length + 1);
  },
  render() {
    return (
      <span>{this.myArray.length}</span>
    );
  }
}

var MyComponent = React.createClass(obj);

// This doesn't change the ponent, since 'obj' isn't used anymore
// by React, it has already copied all properties.
obj.title = 'New title';

// This however affects the ponent, because the reference to the array
// was copied to the ponent prototype, and any changes to what the 
// reference points to will affect everyone who has access to it.
obj.myArray.push(666);
发布评论

评论列表(0)

  1. 暂无评论