Двусторонние привязки React.js:двухуровневый глубокий путь в valueLink

StackOverflow https://stackoverflow.com//questions/21057219

Вопрос

Мое состояние:

[
  {type: "translateX", x: 10},
  {type: "scaleX", x: 1.2}
]

Я использую Помощники двустороннего связывания и я не могу предоставить действительную строку ключа для linkState:

this.state.map(function(item, i) {
  return <div><input valueLink={this.linkState( ??? )}></div>
}

Было бы здорово, если бы this.linkState принял некоторый синтаксис запроса, например "0.type" чтобы получить "translateX" из моего примера.

Есть ли обходные пути?


Я написал Миксин DeepLinkState который является заменой React.addons.LinkedStateMixin.Пример использования:

this.state.map(function(item, i) {
  return <div><input valueLink={this.linkState([i, "x"])}></div>
}

linkState("0.x") также является приемлемым синтаксисом.

Это было полезно?

Решение

Редактировать:

Я понял, что глубокий путь для LinkedState это довольно круто, поэтому я пытаюсь реализовать это.
Код: https://gist.github.com/tungd/8367229
Использование: http://jsfiddle.net/uHm6k/3/


Как говорилось в документе, LinkedState является оберткой вокруг onChange/setState и предназначен для простого случая.Вы всегда можете написать полностью onChange/setState чтобы достичь того, чего вы хотите.Если вы действительно хотите придерживаться LinkedState, вы можете использовать версию без миксина, например:

getInitialState: function() {
    return { values: [
        { type: "translateX", x: 10 },
        { type: "scaleX", x: 1.2 }
    ]}
},
handleTypeChange: function(i, value) {
    this.state.values[i].type = value
    this.setState({ values: this.state.values })
},
render: function() {
    ...
    this.state.values.map(function(item, i) {
        var typeLink = {
            value: this.state.values[i].type,
            requestChange: this.handleTypeChange.bind(null, i)
        }
        return <div><input valueLink={typeLink}/></div>
    }, this)
    ...
}

Вот работающий JSFiddle: http://jsfiddle.net/srbGL/

Другие советы

Вы можете реализовать свой собственный миксин, если базовый миксин вас не удовлетворяет.

Посмотрите, как реализован этот миксин:

var LinkedStateMixin = {
  /**
   * Create a ReactLink that's linked to part of this component's state. The
   * ReactLink will have the current value of this.state[key] and will call
   * setState() when a change is requested.
   *
   * @param {string} key state key to update. Note: you may want to use keyOf()
   * if you're using Google Closure Compiler advanced mode.
   * @return {ReactLink} ReactLink instance linking to the state.
   */
  linkState: function(key) {
    return new ReactLink(
      this.state[key],
      ReactStateSetters.createStateKeySetter(this, key)
    );
  }
};

/**
 * @param {*} value current value of the link
 * @param {function} requestChange callback to request a change
 */
function ReactLink(value, requestChange) {
  this.value = value;
  this.requestChange = requestChange;
}

https://github.com/facebook/react/blob/fc73bf0a0abf739a9a8e6b1a5197dab113e76f27/src/addons/link/LinkedStateMixin.js https://github.com/facebook/react/blob/fc73bf0a0abf739a9a8e6b1a5197dab113e76f27/src/addons/link/ReactLink.js

Таким образом, вы можете легко попытаться написать свой собственный linkState функция на основе вышеизложенного.

linkState: function(key,key2) {
  return new ReactLink(
    this.state[key][key2],
    function(newValue) {
      this.state[key][key2] = newValue;
    }
  );
}

Обратите внимание, что я не использовал ReactStateSetters.createStateKeySetter(this, key). https://github.com/facebook/react/blob/fc73bf0a0abf739a9a8e6b1a5197dab113e76f27/src/core/ReactStateSetters.jsЕще раз взглянув на исходный код, вы обнаружите, что этот метод не так уж и много делает, за исключением того, что он создает функцию и выполняет небольшую оптимизацию кеширования:

function createStateKeySetter(component, key) {
  // Partial state is allocated outside of the function closure so it can be
  // reused with every call, avoiding memory allocation when this function
  // is called.
  var partialState = {};
  return function stateKeySetter(value) {
    partialState[key] = value;
    component.setState(partialState);
  };
}

Так что вам обязательно стоит попробовать написать свой собственный миксин.Это может быть очень полезно, если в вашем состоянии есть сложный объект и вы хотите изменить его через API объекта.

Я делаю это без использования надстройки Value-Link.

Вот демо: http://wingspan.github.io/wingspan-forms/examples/form-twins/

Секретный соус — определить только одну функцию onChange:

onChange: function (path, /* more paths,*/ value) {
    // clone the prior state
    // traverse the tree by the paths and assign the value
    this.setState(nextState);
}

используйте его так:

<input 
    value={this.state['forms']['0']['firstName']} 
    onChange={_.partial(this.onChange, 'forms', '0', 'firstName')} />

Если у вас много (value, onChange) пары, которые вам придется передавать повсюду, возможно, имеет смысл определить абстракцию вокруг этого, подобную ReactLink, но лично я продвинулся довольно далеко без использования ReactLink.

Мои коллеги и я недавно открыли исходный код формы размаха крыльев, библиотека React, которая помогает с глубоко вложенными состояниями.Мы активно используем этот подход.Вы можете увидеть больше примеров демонстраций со связанным состоянием на странице github.

Я написал об этом пост в блоге: http://blog.sendsonar.com/2015/08/04/angular-like-deep-path-data-bindings-in-react/

Но по сути я создал новый компонент, который будет принимать «состояние» родительского элемента и глубокий путь, поэтому вам не придется писать дополнительный код.

<MagicInput binding={[this, 'account.owner.email']} />

Также есть JSFiddle, так что вы можете с ним поиграть.

Вот руководство, объясняющее, как справиться с такими вещами.

Состояние и формы в React, часть 3:Обработка сложного состояния

ТЛ;ДР:

0) Не используйте стандартные ссылки.Использовать эти.

1) Измените свое состояние, чтобы оно выглядело следующим образом:

collection : [
  {type: "translateX", x: 10},
  {type: "scaleX", x: 1.2}
]

2) Перейти по ссылке collection:

var collectionLink = Link.state( this, 'collection' );

3) Перебрать ссылки на его элементы:

collectionLink.map(function( itemLink, i ) {
  return <div><input valueLink={itemLink}></div>
})

Я использовал другой подход, который не использует примеси и не меняет состояние автоматически.

Видеть github.com/mcmlxxxviii/react-value-link

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top