2014-01-11 9 views
16

Mein Zustand ist:React.js 2-Wege-Bindungen: zwei Ebenen tief Weg in Valuelink

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

Ich verwende Two-Way Binding Helpers und ich kann nicht einen gültigen Schlüssel-String für linkState bieten:

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

Wäre schön, wenn this.linkState akzeptiert einige Abfrage-Syntax, wie "0.type", um "translateX" von meinem Beispiel abzurufen.

Gibt es Workarounds?


Ich schrieb DeepLinkState mixin, die ein Drop-in-Ersatz für React.addons.LinkedStateMixin ist. Anwendungsbeispiel:

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

linkState("0.x") ist auch akzeptabel Syntax.

Antwort

19

Edit:

Ich erkannte, dass tief Weg für LinkedState ist ziemlich cool, so versuche ich, es zu implementieren.
Der Code: https://gist.github.com/tungd/8367229
Verbrauch: http://jsfiddle.net/uHm6k/3/


Wie das Dokument angegeben, LinkedState ist ein Wrapper um onChange/setState und für einfachen Fall gemeint. Sie können immer die volle onChange/setState schreiben, um zu erreichen, was Sie wollen. Wenn Sie wirklich mit LinkedState bleiben möchten, können Sie die nicht mixin Version verwenden, zum Beispiel:

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) 
    ... 
} 

Hier ist JSFiddle arbeiten: http://jsfiddle.net/srbGL/

+0

http://jsfiddle.net/uHm6k/1/ erlaubt nicht, "10" und "1.2" zu ändern. – NVI

+0

Problem behoben. Vielen Dank. – tungd

+0

Vielen Dank für Ihre Mixins (Katalysator Repo), @tungd. – seth

1

Sie können Ihre eigene mixin implementieren, wenn die mixin Basis nicht dich zufrieden stellen.

Sehen Sie, wie diese mixin implementiert:

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

So können Sie ganz einfach versuchen, Ihre eigene linkState Funktion basiert zum Schreiben auf dem oben.

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

Beachten Sie, dass ich die ReactStateSetters.createStateKeySetter(this, key) nicht verwendet habe. https://github.com/facebook/react/blob/fc73bf0a0abf739a9a8e6b1a5197dab113e76f27/src/core/ReactStateSetters.js Durch wieder auf den Quellcode suchen, können Sie diese Methode tun nicht so viel herausfinden, außer es eine Funktion erstellt und tut wenig Caching Optimierungen:

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); 
    }; 
} 

So sollten Sie auf jeden Fall versuchen Sie Ihre eigenen mixin zu schreiben . Dies kann sehr nützlich sein, wenn Sie in Ihrem Zustand ein komplexes Objekt haben und es über die Objekt-API modifizieren möchten.

1

Ich mache es ohne Value-Link-Addon zu verwenden. Hier

ist eine Demo: http://wingspan.github.io/wingspan-forms/examples/form-twins/

Die geheime Zutat ist nur eine onChange Funktion zu definieren:

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

verwenden Sie es wie folgt aus:

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

Wenn Sie viele (value, onChange) Paare haben dass man überall herumlaufen muss, es könnte Sinn machen, eine ähnliche Abstraktion wie ReactLink zu definieren, aber ich persönlich bin ziemlich weit weg mit ReactLink.

Meine Kollegen und ich vor kurzem Open Source wingspan-forms, eine React-Bibliothek, die mit tief verschachtelten Zustand hilft. Wir setzen diesen Ansatz stark ein. Auf der Github-Seite können Sie weitere Beispieldemos mit verknüpftem Status sehen.

-1

Ich nahm einen anderen Ansatz spielen kann, die nicht Mixins beschäftigen wird und mutieren nicht automatisch den Zustand

Siehe github.com/mcmlxxxviii/react-value-link

+0

Willkommen bei Stack Overflow! Während dies die Frage beantworten könnte, [wäre es vorzuziehen] (http://meta.stackoverflow.com/q/8259), die wesentlichen Teile der Antwort hier aufzunehmen und den Link als Referenz bereitzustellen. – IKavanagh

1

die hier Anleitung, wie man mit solchen Dingen umgeht.

State and Forms in React, Part 3: Handling the Complex State

TL; DR:

0) Verwenden Sie Standard-Links nicht. Verwenden Sie these.

1) Ändern Sie Ihren Zustand wie folgt aussehen:

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

2) Nehmen Sie Verbindung zum collection:

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

3) eine Iteration durch die Links zu seinen Elementen:

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