2017-02-08 3 views
3

Ich bin ein Anfänger Reagiere Programmierer, kämpfe um zu verstehen, wie ich mit Enkelstaaten umgehen soll (oder ob es eine gute Idee ist, Enkelkinder zu haben).React JS: Wie setze ich Enkelkinder?

Meine Fragen sind ...

1. Ist es möglich, die Enkelkinder über this.setState((prevState)) zu ändern?

2. Haben Enkel als Staaten eine schlechte Idee?

Um zu veranschaulichen, hier ist der Konstruktor einer Komponente.

constructor(props) { 
super(props); 
this.state = { 
    input: { 
    example: "", 
    }, 
    invalid:{ 
    example: false 
    }, 
}; 
this.handleChange = this.handleChange.bind(this); 
this.submit = this.submit.bind(this); 
} 

Ich sehe this.state.invalid als Kind und this.state.invalid.example als Enkelkind.

Hier ist ein JSX.

<div className="input"> 
    <input type="text" value={this.state.input.example || ''} onChange={this.handleChange} /> 
    { this.state.invalid.example ? <span> This input is invalid </span> : null } 
</div> 
//Here are similar input fields... 

<button onClick={this.submit} type="button">Submit</button> 

Wenn die onClick={this.submit} abgefeuert wird, ich möchte die Eingabe in der Funktion bestätigen, ‚this.submit‘.

submit(){ 
for (var key in this.state.input) { 
    if(!this.state.input[key]){ 
    this.setState((prevState, key) => ({ 
     invalid[key]:true, //This causes an error, saying that "SyntaxError: Unexpected token, expected ," 
    })); 
    } 
} 

In diesem Beispiel wird this.state.invalid.example soll eingestellt werden (das heißt geändert), aber der obige Code funktioniert nicht.

Vielleicht ist es eine bessere Idee, diese App zu zerlegen und <div className="input"> eine einzige Komponente zu machen. Bevor ich das tue, möchte ich klären, ob es möglich ist, Enkel auf diese Weise zu gründen.

Da ich niemanden um mich herum kenne, der ReactJS lernt, wird jeder Ratschlag geschätzt!

+1

Mögliche duplizieren: http://stackoverflow.com/questions/18933985/this-setstate-isnt-merging-states-as-i-would-expect – forrert

+0

Nicht genau das, was ich gesucht habe ... aber das war sehr informativ. Danke für das Teilen! – Hiroki

Antwort

3

Sie können den Status der Vorgängerkomponente nicht an die untergeordnete Komponente nach Status übergeben. Sie können es durch Requisiten tun, aber es führt zu Requisiten viele Ebenen nach unten. Es gibt auch eine Möglichkeit mit context, aber es ist auch nicht gut.

Der beste Weg ist entweder Flussmittel oder Redox zu verwenden. Ich bevorzuge redux und in redux können Sie die Variablen, die Ihr Objekt benötigt, aus einem Speicher abrufen, indem Sie die Methode connect verwenden.

https://github.com/reactjs/react-redux/blob/master/docs/api.md

auch zu prüfen these videos

+0

Entschuldigung für diese späte Antwort. Ich habe viele Dinge ausprobiert, und jetzt habe ich das Gefühl, dass Redux die beste Lösung für mein Projekt ist. Vielen Dank! – Hiroki

2

Ich glaube nicht, es ist per se eine schlechte Idee seinen Zustand in einer Komponente verschachtelt. Es ist jedoch wichtig, sich daran zu erinnern, dass setState

führt eine flache merge von nextstate in aktuellen Zustand

siehe in the react documentation.

Also, wenn Ihr Zustand ist

{ 
    input: { 
    example: "asd", 
    other: "123" 
    }, 
    invalid: { 
    example: false, 
    other: false 
    } 
} 

und Sie setState({invalid: {example: true}}) rufen, dann wird der resultierende Zustand wie

{ 
    input: { 
    example: "asd", 
    other: "123" 
    }, 
    invalid: { 
    example: true 
    } 
} 

Hinweis unter invalid das alles wurde mit dem neuen Zustand, während das Objekt ersetzt aussehen würde unter input wurde unberührt gelassen (dh eine flache Zusammenführung wurde durchgeführt).

In Ihrer submit Funktion, würde ich das gesamte invalid Objekt in der Schleife erstellen und setState wie diese dann rufen: setState({invalid: invalid}).

Der Fehler in Ihrem letzten Code-Segment ist einfach ein Syntaxfehler. Sie können ein Objekt wie folgt nicht erstellen: {invalid[key]:true}, es sollte {invalid: {[key]: true}} sein.

+0

Vielen Dank für Sie Code. Vielleicht funktioniert '{invalid: {example: true}}', aber diese Syntax mit 'this.setState ((prevState, key))' funktionierte nicht. Anscheinend wird 'key' als Feldname behandelt (d. H.' Invalid: {key: true} ') – Hiroki

+0

Außerdem habe ich gerade bemerkt, dass Sie' setState' mit einer Funktion als erstem Argument aufrufen. Nicht ganz sicher, woher Sie das haben, aber 'setState' erwartet ein Objekt als erstes Argument, das flach in den aktuellen Zustand übergeht (d. H. Eine Top-Level-Eigenschaft wird überschrieben). – forrert

0

Wenn Sie dies tun wollen, die Art und Weise, es zu tun ist:

constructor() { 
    this.state = { 
     input: { 
      example: "", 
     }, 
     invalid:{ 
      example: false 
     }, 
    }; 
} 

assignChildState(state) { 
    var state = Object.assign({}, this.state); 
    state.input = Object.assign({}, state.input); 
    state.input.example = "New Value"; 
    this.setState(state); 
} 

Sie natürlich eine Funktion, es zu handhaben schaffen könnte, so etwas wie:

function assignChildState(path, value) { 
    var pieces = path.split("."); 
    var state = Object.assign({}, this.state); 
    var current = state; 
    for (var i = 0; i < pieces.length - 1; i++) { 
     var piece = pieces[i]; 
     console.log(current, piece); 
     if (current[piece].toString() === "[object Object]") { 
      current[piece] = Object.assign({}, current[piece]); 
     } else if (typeof current[piece] === "object" /* array */) { 
      current[piece] = current[piece].concat(); 
     } 
     current = current[piece]; 
    } 
    current[pieces[i]] = value; 
    this.setState(state); 
} 

Und dann können Sie tun:

this.assignChildState("input.example", true); 

und es wird den Kind-Status entsprechend aktualisieren.

Alles was gesagt wird, würde ich auf jeden Fall Redux oder Flux, oder meine persönliche Lieblingsflummox suchen.