2017-04-25 4 views
3

Ich gehe durch ein Tutorial für Todo-Liste in React und lief in den folgenden Fehler, ich habe eine ganze Weile verbracht und kann einfach nicht den Fehler finden .. hier ist der Fehler und die Code für die Komponente und das ist der Code für den Kurs Repo (Problem auf dieser begehen erscheint):React eindeutige "Schlüssel" Fehler

https://github.com/andrewjmead/react-course-todo-app/commit/0521f151705f78cb9f8d69262eb093f1431cb9ca

Jede Hilfe sehr geschätzt.

Warnung: Jedes untergeordnete Element in einem Array oder Iterator sollte eine eindeutige "Schlüssel" -Stütze haben. Überprüfen Sie die Rendermethode TodoList. Weitere Informationen finden Sie unter fb.me/react-warning-keys.

Auch gibt es einen Fehler im Terminal, für die Ausbreitung des Bedieners bei TOGGLE_TODO

return { 
...todo, // here 
completed: nextCompleted, 
completedAt: nextCompleted ? moment().unix() : undefined 
}; 

var React = require('react'); 
var { connect } = require('react-redux'); 
import Todo from 'Todo'; 
var TodoAPI = require('TodoAPI'); 

export var TodoList = React.createClass ({ 
    render: function() { 
     var { todos, showCompleted, searchText } = this.props; 
     var renderTodos =() => { 
      if(todos.length === 0) { 
       return (
        <p className="container__message">No tasks</p> 
       ); 
      } 
      return TodoAPI.filterTodos(todos, showCompleted, searchText).map((todo) => { 
       return (
        //add unique key prop to keep track of individual components 
        <Todo key={todo.id} {...todo} /> 
       ); 
      }); 
     }; 
     return (
      <div> 
       {renderTodos()} 
      </div> 
     ); 
    } 
}); 

export default connect(
    (state) => { 
     return state; 
    } 
)(TodoList); 

Reduzierungen:

var uuid = require('uuid'); 
var moment = require('moment'); 

export var searchTextReducer = (state = '', action) => { 
    switch (action.type) { 
     case 'SET_SEARCH_TEXT': 
      return action.searchText; 
     default: 
      return state; 
    }; 
}; 

export var showCompletedReducer = (state = false, action) => { 
    switch (action.type) { 
     case 'TOGGLE_SHOW_COMPLETED': 
      return !state; 
     default: 
      return state; 
    };  
}; 

export var todosReducer = (state = [], action) => { 
    switch(action.type) { 
     case 'ADD_TODO': 
      return [ 
       ...state, 
       { 
        text: action.text, 
        id: uuid(), 
        completed: false, 
        createdAt: moment().unix(), 
        completedAt: undefined     
       } 
      ]; 
     case 'TOGGLE_TODO': 
      return state.map((todo) => { 
       if(todo.id === action.id) { 
        var nextCompleted = !todo.completed; 

        return { 
         ...todo, 
         completed: nextCompleted, 
         completedAt: nextCompleted ? moment().unix() : undefined 
        }; 
       } else { 
        return todo; 
       } 
      }); 
     case 'ADD_TODOS': 
      return [ 
       ...state, 
       ...action.todos 
      ]; 
     default: 
      return state; 
    } 
}; 


Webpack: 

var webpack = require('webpack'); 

module.exports = { 
    entry: [ 
    'script!jquery/dist/jquery.min.js', 
    'script!foundation-sites/dist/js/foundation.min.js', 
    './app/app.jsx' 
    ], 
    externals: { 
     jquery: 'jQuery' 
    }, 
    plugins: [ 
     new webpack.ProvidePlugin({ 
      '$': 'jquery', 
      'jQuery': 'jquery' 
     }) 
    ], 
    output: { 
    path: __dirname, 
    filename: './public/bundle.js' 
    }, 
    resolve: { 
    root: __dirname, 
    modulesDirectories: [ 
     'node_modules', 
     './app/components', 
     './app/api' 
    ], 
    alias: { 
     applicationStyles: 'app/styles/app.scss', 
     actions: 'app/actions/actions.jsx', 
     reducers: 'app/reducers/reducers.jsx', 
     configureStore: 'app/store/configureStore.jsx' 
    }, 
    extensions: ['', '.js', '.jsx'] 
    }, 
    module: { 
    loaders: [ 
     { 
     loader: 'babel-loader', 
     query: { 
      presets: ['react', 'es2015'] 
     }, 
     test: /\.jsx?$/, 
     exclude: /(node_modules|bower_components)/ 
     } 
    ] 
    }, 
    devtool: 'cheap-module-eval-source-map' 
}; 

Antwort

3

Knoten-uuid ist veraltet, hier überprüfen: https://www.npmjs.com/package/uuid

Sie Ihre package.json UUID durch die Installation aktualisieren können und sehen, ob es hilft:

npm installieren Uuid

Nur nicht vergessen zu aktualisieren var uuid = require ('node-uuid'); zu var uuid = erfordern ('uuid'); in Ihren anderen Dateien.

P.S. Haben Sie beim Ausführen eines Webpacks Fehler in Ihrem Terminal?

+2

können Sie Ihre Reducers/Actions-Datei teilen? – Joe

+0

dort habe ich den Beitrag bearbeitet – Smithy

+1

es scheint, dass Sie Babel Stage-0 in Ihrem Webpack vermissen, wenn Sie den Spread-Operator Fehler erhalten, versuchen Sie die Installation Npm installieren --Save-Dev Babel-Preset-Stufe-0 – Joe

2

Ich wette todo.id ist undefined und daher nicht eindeutig. Können Sie in Ihrem Beispiel todos einschließen?

+0

Bitte überprüfen Sie die Antwort auf bntzio's Beitrag der gesamte Code ist auf dem Link enthalten – Smithy

2

Sie können index param auf Ihre map Funktion hinzuzufügen, übergeben Sie dann diesen Index auf Ihre Todo Komponente:

export var TodoList = React.createClass ({ 
    render: function() { 
     var { todos, showCompleted, searchText } = this.props; 
     var renderTodos =() => { 
      if(todos.length === 0) { 
       return (
        <p className="container__message">No tasks</p> 
       ); 
      } 
      return TodoAPI.filterTodos(todos, showCompleted, searchText).map((todo, index) => { // here <==== 
       return (
        //add unique key prop to keep track of individual components 
        <Todo key={`key-${index}`} {...todo} /> 
       ); 
      }); 
     }; 
     return (
      <div> 
       {renderTodos()} 
      </div> 
     ); 
    } 
}); 
+0

Seien Sie vorsichtig mit diesem Ansatz; es kann Probleme verursachen, wenn Sie das Elternteil mit anderen 'Todos' jemals wieder rendern, da die Schlüssel wiederverwendet werden. –

+0

Ok, das werde ich im Hinterkopf behalten. Nur eine Frage: Wenn die Kinder ändern, wie die Wiederverwendung der Schlüssel ein Problem verursachen könnte? weil die alten Kinder werden entfernt und ihre Schlüssel mit ihnen (Nun, ich denke, das ist, wie es passiert) –

+0

danke Ich habe das schon vorher versucht, aber ich habe immer noch den gleichen Fehler ... – Smithy

3

In Reaktion, wenn Sie mehrere gleiche Komponenten (in Ihrem Fall die todos) Rendering werden Sie brauchen um jedem einzelnen einen eindeutigen Schlüssel hinzuzufügen, weil React wissen muss, wie sie im virtuellen Dom behandelt werden sollen.

können Sie verschiedene Dinge tun, um dies zu beheben:

  1. In der for-Schleife, eine Indexvariable erstellen und erhöhen um 1 jedesmal, wenn eine Schleife beendet ist, dann eingestellt, dass der Schlüssel für jede gerenderte Komponente .

  2. Wenn Sie Ihre Todos von einer API abrufen, legen Sie für jede Aufgabe eine ID fest und verwenden Sie sie als Ihren Komponentenschlüssel.

  3. Verwenden Sie einen Zufallsgenerator, um einen eindeutigen Schlüssel auf jedem Ihrer Todos zu setzen.

Die besten Ansätze sind die # 2 und # 3, ich sehe, dass Sie versuchen, die # 2 (Einstellung der Schlüssel von todo id) in Ihrem Fall zu tun, aber ich denke, es ist nicht definiert ist, überprüfen Sie es.

Eine andere Lösung ist die Verwendung eines uuid für jede gerenderte Komponente/Todo.

Um dies zu tun, können Sie node-uuid installieren.

Run: npm i --save node-uuid

Dann in der Datei den Import tun: import uuid from 'node-uuid' oder const uuid = require('node-uuid')

Jetzt Ihren Code ändern, so zu sein:

return TodoAPI.filterTodos(todos, showCompleted, searchText).map((todo) => { 
    return (
    //add unique key prop to keep track of individual components 
    <Todo key={uuid()} {...todo} /> 
); 
}); 

Und dann sind Sie gut zu gehen .

+0

Ja, ich habe es in der Elternkomponente (TodoApp), Ich habe Ihre Lösung versucht, aber ich bekomme immer noch die gleiche Fehlermeldung .. Mein Code ist auf dem neuesten Stand mit dem Lehrer, auch wenn ich seinen Code klonen und herumspielen Ich bekomme den Fehler. Es ist also der identische Code, bis zu diesem Commit: https://github.com/andrewjmead/react-course-todo-app/commit/0521f151705f78cb9f8d69262eb093f1431cb9ca – Smithy

Verwandte Themen