2016-05-15 3 views
0

Я изучаю redux & реагирую и создаю список задач. Я читал и смотрел разные статьи, но не мог понять, чего мне не хватает в моей настройке.React Redux не может получить редуктор для подбора действий

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

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

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; 
    } 
} 
+1

В 'TodoListComponent.jsx', вы должны использовать' addTodo' переданные в 'props' через' connect' – topheman

+2

В качестве примечания к ответам ниже, при работе в Redux ваши редукторы всегда должны возвращать новый экземпляр состояния, а не манипулировать текущим состоянием, а не возвращать todos.push (Map (action.payload)); 'который изменяет текущий массив, который вы должны использовать' return todos.concat (Map (action.payload)); ', который вернет новый массив из вашего текущего состояния и полезной нагрузки. –

ответ

1

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

Так что ваши 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); 
    } 
    } 

} 
+0

Спасибо за объяснение, имеет смысл. Это сработало, в вашем ответе отсутствовал 'onKeyDown = {this.onSubmit.bind (this)}', который был предложен в ответе @opheman. – Allanp

2
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.bind(this)} /> 
     <ul> 
      {todos.map(c => (
      <li key={t.id}> 
       <TodoComponent todo={t} styleName='large' /> 
      </li> 
     ))} 
     </ul> 
     </div> 
    ) 
    } 

    onSubmit(e) { 
    // use the addTodo passed via connect 
    const { addTodo } = this.props; 
    const input = e.target; 
    const text = input.value; 
    const isEnterKey = (e.which === 13); 

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

} 
Смежные вопросы