Подтвердить что ты не робот

React.js: перезапись setState, а не слияние

Я совершенно новый, чтобы реагировать. Я и в процессе экспериментирования создаю макет стиля макета.

Я визуализирую каждый элемент в DOM, тогда мне нужно перебрать каждый элемент и применить положения x и y на основе предыдущих элементов.

Начальная модель выглядит следующим образом:

[
  {
    "title": "The Forrest",
    "description": "some cool text",
    "imgSmallSrc": "/img/img4-small.jpg",
    "imgAlt": "Placeholder image",
    "tags": [
        "Design",
        "Mobile",
        "Responsive"
    ],
    "date": 1367154709885,
    "podStyle": {
      "width": 253
    }
  }
]

(Я только показал один элемент, чтобы все было в порядке).

Как только я закончу цикл и получаю свои данные x и y, я хочу применить это к объекту podStyle. Я вызываю setState со следующими данными:

[
  {
    "podStyle": {
      "x": 0,
      "y": 0,
      "height": 146,
      "width": 253
    }
  }
]

Это, кажется, удаляет все текущие данные из модели и оставляет меня только с данными podStyle. Я не понимаю, как работает это слияние?

Заранее благодарим за помощь!

4b9b3361

Ответ 1

Если ваше состояние является объектом:

getInitialState: function() {
  return { x: 0, y: 0 };
}

вы можете использовать setState для установки отдельных клавиш на этом объекте:

this.setState({ x: 1 }); // y still == 0

Реагирует не интеллектуальное слияние вашего состояния; например, это не работает:

getInitialState: function() {
  return {
    point: { x: 0, y: 0 },
    radius: 10
  };
}

this.setState({point: {x: 1}});
// state is now == {point: {x: 1}, radius: 10} (point.y is gone)

[изменить]

Как уже упоминалось @ssorallen, вы можете использовать помощники неизменяемости, чтобы получить эффект, который вам нужен:

var newState = React.addons.update(this.state, {
  point: { x: {$set: 10} }
});
this.setState(newState);

Смотрите этот JSFiddle для примера: http://jsfiddle.net/BinaryMuse/HW6w5/

Ответ 2

Слияние нечетное, поэтому this.setState({point}) оставляет (ed: this.state.radius) неповрежденным, но полностью заменяет (ed: this.state.point).

https://facebook.github.io/react/docs/state-and-lifecycle.html#state-updates-are-merged

Чтобы предложить ответы ES7 + на уже предоставленные ответы, используйте transform-object-rest-spread вместо Object.assign():

class MyComponent extends React.Component {
    state = {
        point: { 
            x: 0, 
            y: 0,
        },
        radius: 10,
    }

    handleChange = () => {
        this.setState({
            point: {
                // rest operator (...) expands out to:
                ...this.state.point, // x:0, y:0,
                y: 1, // overwrites old y
            },
            // radius is not overwritten by setState
        });
    }

    render() {
        // omitted
    }
}

.babelrc(также требует transform-class-properties с этапа предустановки Babel 2)

{
    "presets": ["es2015", "stage-2", "react"],
    "plugins": ["transform-object-rest-spread"],
}

Ответ 3

Что-то вроде:

getInitialState: function() {
    return {
        something: { x: 0, y: 0 },
        blah: 10
    };
}

var state = Object.assign(this.state, {
    something: Object.assign(this.state.something, { y: 50 }),
});

this.setState(state);

Было бы лучше, если бы оно было рекурсивным/глубоким, а не жестким кодированием дерева, но я оставлю это до читателя:)