React Redux не может получить редуктор для выполнения действий

Я учился сокращать и реагировать, и я составляю список дел. Я читал и просматривал разные статьи, но не могу понять, чего мне не хватает в моей настройке.

В настоящее время вы можете добавить задачу через ввод. При нажатии Enter он отправляет addTodo действие с текстом задачи.

Я ожидаю, что редуктор увидит тип действия и обновит состояние, но этого не происходит. Что мне не хватает?

index.jsx

import React from 'react';
import ReactDOM from 'react-dom';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import reducer from './reducer.js';
import TodoList from './containers/container.js';

const store = createStore(reducer);

ReactDOM.render(
  <Provider store={store}>
    <TodoList />
  </Provider>,
document.getElementById('app'));

actions.js

var uuid = require('node-uuid');

export function addTodo(text) {
  console.log('action addTodo', text);
  return {
    type: 'ADD_TODO',
    payload: {
      id: uuid.v4(),
      text: text
    }
  };
}

TodoListComponent.jsx

import React from 'react';
import TodoComponent from './TodoComponent.jsx';
import { addTodo } from '../actions/actions.js'

export default class TodoList extends React.Component {

  render () {
    const { todos } = this.props;

    return (
      <div>
        <input type='text' placeholder='Add todo' onKeyDown={this.onSubmit} />
        <ul>
          {todos.map(c => (
            <li key={t.id}>
              <TodoComponent todo={t} styleName='large' />
            </li>
          ))}
        </ul>
      </div>
    )
  }

  onSubmit(e) {
    const input = e.target;
    const text = input.value;
    const isEnterKey = (e.which === 13);

    if (isEnterKey) {
      input.value = '';
      addTodo(text);
    }
  }

}

TodoComponent.jsx

import React from 'react';
import CSSModules from 'react-css-modules';
import styles from './style.css';

export default class TodoComponent extends React.Component {

  render () {
    const { todo } = this.props;

    return (
      <div styleName='large'>{todo.text}</div>
    )
  }
}

export default CSSModules(TodoComponent, styles);

container.js

import { connect } from 'react-redux';
import TodoList from '../components/TodoListComponent.jsx';
import { addTodo } from '../actions/actions.js';

const mapStateToProps = (state) => {
   return {
      todos: state
   }
};

const mapDispatchToProps = (dispatch) => {
   return {
      addTodo: text => dispatch(addTodo(text))
   }
};

export default connect(mapStateToProps, mapDispatchToProps)(TodoList);

reducer.js

import { List, Map } from 'immutable';

const init = List([]);

export default function(todos = init, action) {

  console.log('reducer action type', action.type);

  switch(action.type) {
    case 'ADD_TODO':
      console.log('ADD_TODO');
      return todos.push(Map(action.payload));
    default:
      return todos;
  }
}

person Allanp    schedule 15.05.2016    source источник
comment
В TodoListComponent.jsx следует использовать addTodo, переданный в props через connect   -  person topheman    schedule 15.05.2016
comment
В качестве побочного примечания к ответам ниже, при работе в Redux ваши редукторы всегда должны возвращать новый экземпляр состояния, не манипулируя текущим состоянием, поэтому вместо return todos.push(Map(action.payload));, который изменяет текущий массив, вы должны использовать return todos.concat(Map(action.payload));, который вернет новый массив из ваше текущее состояние и полезная нагрузка действия.   -  person Brad Colthurst    schedule 15.05.2016


Ответы (1)


В вашем TodoListComponent вы импортируете свои действия непосредственно из файла действий, но на самом деле вы хотите использовать действие, которое вы сопоставляете для отправки и передачи как свойство в контейнере. Это объясняет, почему вы видите журналы от действий, но не от редуктора, поскольку действие никогда не отправляется в магазин.

Итак, ваш TodoListComponent должен быть:

import React from 'react';
import TodoComponent from './TodoComponent.jsx';

export default class TodoList extends React.Component {

  render () {
    const { todos } = this.props;

    return (
      <div>
        <input type='text' placeholder='Add todo' onKeyDown={this.onSubmit} />
        <ul>
          {todos.map(c => (
            <li key={t.id}>
              <TodoComponent todo={t} styleName='large' />
            </li>
          ))}
        </ul>
      </div>
    )
  }

  onSubmit(e) {
    const input = e.target;
    const text = input.value;
    const isEnterKey = (e.which === 13);

    if (isEnterKey) {
      input.value = '';
      this.props.addTodo(text);
    }
  }

}
person Július Retzer    schedule 15.05.2016
comment
Спасибо за объяснение, имеет смысл. Это сработало, в вашем ответе отсутствовал `onKeyDown = {this.onSubmit.bind (this)}`, который был предложен в ответе @opheman. - person Allanp; 15.05.2016