#javascript #reactjs #redux #react-redux
#javascript #reactjs #redux #react-redux
Вопрос:
render() {
const listItems = this.props.todos.map((todo) =>
<ListItem key={todo.id} id={todo.id} content={todo.content} onEdit={this.onEditItem}/>
)
return <>
<ul className="todo-list">
{listItems}
</ul>
{/* <AddItem/> */}
<div className="add-item">
<input type="text" onChange={this.onChangeValue}/>
<button type="submit" onClick={this.onAddItem}>Add Item</button>
</div>
</>
}
onAddItem = () => {
this.props.submitNewTodo({ id: this.props.todos.length 1, content: this.state.value})
};
Когда я console.log this.props.todos.length
, он возвращает значение 2 и this.state.value
возвращает значение, введенное во ввод. Но кнопка «Добавить элемент» не работает.
Я сопоставил submitNewTodo
с dispatch addTodo(newTodo)
следующим образом
const mapDispatchToProps = (dispatch) => {
return {
submitNewTodo: function(newTodo) {
dispatch(addTodo(newTodo));
}
}
}
Полный код находится в этом codepen .
Ответ №1:
Ваш addTodo
создатель действия ошибается:
const addTodo = (todo) => {
type: 'ADD_TODO',
todo
};
это метод, который обрабатывает
type: 'ADD_TODO',
todo
как тело метода. ( type
используется в качестве метки разрыва для строки 'ADD_TODO'
, за которой следует todo
)
Если вы хотите вернуть действие, эти два обозначения верны:
const addTodo = (todo) => {
return {
type: 'ADD_TODO',
todo
}
};
// note the parantheses!
const addTodo = (todo) => ({
type: 'ADD_TODO',
todo
});
Комментарии:
1. Кроме того, общее замечание: это очень старый стиль redux, если вы изучаете redux прямо сейчас, возможно, вы следуете очень старому учебному пособию, которое научит вас стилю redux, который в конечном итоге будет намного длиннее, чем требуется на самом деле. Пожалуйста, следуйте официальным руководствам: redux.js.org/tutorials/index
Ответ №2:
Первое, что я замечаю в вашем коде, это то, что ваш редуктор не следует шаблону, используемому Redux.
const todoReducer = ( state = [{ id: 1, content: "Call Client" },
{ id: 2, content: "Write Log" }], action ) => {
if (action.type == ADD_TODO) {
return state.concat(action.todo);
}
else {
return state;
}
}
Первое правило, которое он нарушает, заключается в том, что это должен быть переключатель, а не оператор if .
switch (action.type) {
case 'ADD_TODO':
// create new todos with the added todo
const newTodos = [
...state.todos,
action.payload.todo,
]
// new state object
return {
...state,
todos: newTodos,
}
default:
return {
...state,
}
}
Второе правило заключается в том, что вы хотите всегда иметь свойство полезной нагрузки, чтобы следовать правильным шаблонам потока. Эта полезная нагрузка будет содержать все ваши данные.
const addTodo = (todo) => {
type: 'ADD_TODO',
payload: {
todo,
}
};
Комментарии:
1. Я уже использовал компонент connect из react-redux вот так
const Container = connect(mapStateToProps, mapDispatchToProps)(Presentational);
2. вы можете просмотреть весь код моего приложения здесь: codepen.io/blenderous/pen/MWjdyoN?editors=0011
3. Привет, случайный сопровождающий redux. Просто чтобы прояснить это: switch может быть соглашением (и только в старых стилях redux, современный redux в целом сильно отличается), но определенно не является фиксированным правилом. То же самое касается свойства полезной нагрузки. Это не необходимость, только соглашение.
4. Справедливо, я полагаю, что это не остановит компиляцию кода, но определенно значительно упростит отладку.