2017-07-07 3 views
2

Ich lerne React und für das Training möchte ich eine grundlegende Todo App erstellen. Für den ersten Schritt möchte ich eine Komponente namens AddTodo erstellen, die ein Eingabefeld und eine Schaltfläche rendert und jedes Mal, wenn ich etwas in das Eingabefeld eingib und den Knopf drücke, möchte ich den Wert des Eingabefeldes an eine andere aufgerufene Komponente übergeben TodoList und an die Liste anhängen.Uncaught RangeError Maximale Callstackgröße in React App überschritten

Das Problem ist, wenn ich die App starte, die AddTodo Komponente rendert erfolgreich aber wenn ich etwas eingeben und die Taste drücken, reagiert die App für 2 Sekunden und danach bekomme ich das: Uncaught RangeError: Maximum call stack size exceeded und nichts passiert.

Code Meine app Quelle: Main.jsx

import React, {Component} from 'react'; 
import TodoList from 'TodoList'; 
import AddTodo from 'AddTodo'; 

class Main extends Component { 
    constructor(props) { 
     super(props); 
     this.setNewTodo = this.setNewTodo.bind(this); 
     this.state = { 
      newTodo: '' 
     }; 
    } 
    setNewTodo(todo) { 
     this.setState({ 
      newTodo: todo 
     }); 
    } 
    render() { 
     var {newTodo} = this.state; 
     return (
      <div> 
       <TodoList addToList={newTodo} /> 
       <AddTodo setTodo={this.setNewTodo}/> 
      </div> 
     ); 
    } 
} 
export default Main; 

AddTodo.jsx

import React, {Component} from 'react'; 

class AddTodo extends Component { 
    constructor(props) { 
     super(props); 
     this.handleNewTodo = this.handleNewTodo.bind(this); 
    } 
    handleNewTodo() { 
     var todo = this.refs.todo.value; 
     this.refs.todo.value = ''; 
     if (todo) { 
      this.props.setTodo(todo); 
     } 
    } 
    render() { 
     return (
      <div> 
       <input type="text" ref="todo" /> 
       <button onClick={this.handleNewTodo}>Add to Todo List</button> 
      </div> 
     ); 
    } 
} 
AddTodo.propTypes = { 
    setTodo: React.PropTypes.func.isRequired 
}; 
export default AddTodo; 

TodoList.jsx

import React, {Component} from 'react'; 

class TodoList extends Component { 
    constructor(props) { 
     super(props); 
     this.renderItems = this.renderItems.bind(this); 
     this.state = { 
      todos: [] 
     }; 
    } 
    componentDidUpdate() { 
     var newTodo = this.props.addToList; 
     var todos = this.state.todos; 
     todos = todos.concat(newTodo); 
     this.setState({ 
      todos: todos 
     }); 
    } 
    renderItems() { 
     var todos = this.state.todos; 
     todos.map((item) => { 
      <h4>{item}</h4> 
     }); 
    } 
    render() { 
     return (
      <div> 
       {this.renderItems()} 
      </div> 
     ); 
    } 
} 
export default TodoList; 

Antwort

1

Zum ersten Mal componentDidUpdate genannt wird (die nach dem ersten Wechsel geschieht in seinem Requisiten/Zustand, der in Ihrem Fall passiert, nachdem er zuerst Todo hinzugefügt hat) fügt erhinzuzu this.state.todo und Updates Zustand. Der Update-Zustand wird wieder componentDidUpdate laufen lassen und es fügt den Wert von this.props.addToList wieder zu "this.state.todo" hinzu und es geht unendlich weiter.

Sie können es mit einigen schmutzigen Hacks beheben, aber Ihre Vorgehensweise ist insgesamt ein schlechter Ansatz. Richtige zu tun ist todos in übergeordneter Komponente zu halten (Main), fügen Sie die neue Aufgabe, um es in setNewTodo (Sie es wahrscheinlich zu addTodo umbenennen können) und die todos Liste von Main Zustand TodoList passieren: <TodoList todos={this.state.todos}/> zum Beispiel.

1

Die Grundidee von react ist, wann immer Sie die Funktion setState aufrufen, die Komponente react wird aktualisiert, wodurch die Funktion componentDidUpdate erneut aufgerufen wird, wenn die Komponente aktualisiert wird.

Jetzt Problem hier ist, rufen Sie SetState-Funktion in ComponentDidUpdate, die die Komponente erneut aktualisiert und diese Kette geht für immer weiter. Und jedes Mal, wenn componentDidUpdate aufgerufen wird, wird ein Wert für den Todo erstellt. Es kommt also eine Zeit, in der der Speicher voll wird und einen Fehler auslöst. Sie sollten nicht setState Funktion innerhalb von Funktionen wie componentWillUpdate, componentDidUpdate usw.

Eine Lösung kann sein nennen componentWillReceiveProps statt componentDidUpdate Funktion wie folgt zu verwenden:

 componentDidUpdate(nextProps) { 
      var newTodo = nextProps.addToList; 
      this.setState(prevState => ({ 
       todos: prevState.todos.concat(newTodo) 
      })); 
     } 
Verwandte Themen