2016-11-09 29 views
1

因此,我一直在通過Dan Abramov的Redux教程來構建一個簡單的待辦事項應用程序。下面是主要的渲染功能的代碼,爲什麼切換待辦事項在Redux中不起作用?

const todo = (state, action) => { 
    switch(action.type){ 
     case 'ADD_TODO': 
      return { 
       id: action.id, 
       text: action.text, 
       completed: false 
      } 
     case 'TOGGLE_TODO': 
      if(state.id !== action.id){ 
       return state 
      } 
      return {...state, 
       completed: !state.completed 
      } 

     default: 
      return state 
    } 
} 

const todos = (state = [], action) => { 
    switch(action.type){ 
     case "ADD_TODO": 
      return [ 
       ...state, 
       todo(undefined, action) 
      ] 
     case "TOGGLE_TODO": 
      return state.map(t => { 
       todo(t, action) 
      }) 
     default: 
      return state; 
    } 
} 

const visibilityFilter = (state = 'SHOW_ALL', action) => { 
    switch(action.type){ 
     case 'SET_VISIBILITY_FILTER': 
      return action.filter 
     default: 
      return state 
    } 
} 


const todoApp = combineReducers({ 
    visibilityFilter, 
    todos 
}); 

const store = createStore(todoApp); 

const FilterLink = ({ 
    filter, 
    currentFilter, 
    children 
}) => { 
    if(filter === currentFilter){ 
     return <span>{children}</span> 
    } 
    return (
     <a href='#' onClick={e => { 
      e.preventDefault(); 
      store.dispatch({ 
       type: 'SET_VISIBILITY_FILTER', 
       filter 
      }) 
     }}> 
      {children} 
     </a> 
    ) 
} 

const Todo = ({ 
    onClick, 
    completed, 
    text 
}) => (
    <li onClick={(onClick)} 
    style={{textDecoration: completed ? 'line-through' : 'none'}}> 
     {text} 
    </li> 
); 

const TodoList = ({ 
    todos, 
    onTodoClick 
}) => (
    <ul> 
     {todos.map(todo => 
      <Todo key={todo.id} {...todo} 
      onClick={() => onTodoClick(todo.id)} /> 
     )} 
    </ul> 
); 

const getVisibleTodos = (todos, filter) => { 
    switch(filter){ 
     case 'SHOW_ALL': 
      return todos; 
     case 'SHOW_COMPLETED': 
      return todos.filter(
       t => t.completed 
      ) 
     case 'SHOW_ACTIVE': 
      return todos.filter(
       t => !t.completed 
      ) 
    } 
} 

let nextTodoId = 0; 
class TodoApp extends React.Component { 
    render() { 
     const { 
      todos, 
      visibilityFilter 
     } = this.props 
     const visibleTodos = getVisibleTodos(todos, visibilityFilter); 
     return (
      <div> 
       <input ref={text => { 
        this.input = text; 
       }} /> 
       <button onClick={() => { 
        store.dispatch({ 
         type:"ADD_TODO", 
         text: this.input.value, 
         id: nextTodoId++ 
        }); 
        this.input.value = ''; 
       }}>Add a todo 
       </button> 
       <TodoList todos={visibleTodos} onTodoClick={id => store.dispatch({ 
        type: 'TOGGLE_TODO', 
        id 
       })} /> 
       <p> 
        Show: 
        {' '} 
        <FilterLink filter='SHOW_ALL' currentFilter={visibilityFilter}> 
         All 
        </FilterLink> 
        {' '} 
        <FilterLink filter='SHOW_COMPLETED' currentFilter={visibilityFilter}> 
         Completed 
        </FilterLink> 
        {' '} 
        <FilterLink filter='SHOW_ACTIVE' currentFilter={visibilityFilter}> 
         Active 
        </FilterLink> 
       </p> 
      </div> 
     ) 
    } 
} 



const render =() => { 
    console.log(store.getState()); 
    ReactDOM.render(<TodoApp {...store.getState()}/>, document.getElementById('root')); 
} 

store.subscribe(render); 
render(); 

當我嘗試切換待辦事項,我得到以下錯誤,

index.js:170 Uncaught TypeError: Cannot read property 'id' of undefined

現在,當我試圖註銷this.props.todos在我嘗試切換待辦事項時,它返回未定義。這就是我得到錯誤的原因,因爲由於某些原因,this.props.todos沒有被傳遞給click事件。但是,我仔細閱讀了課程筆記,並且具有完全相同的代碼。我在這裏做錯了什麼?我該如何解決它?

+0

你可以看到數據時,你CONSOLE.LOG(this.props.todos) –

+0

是它在github? – abhirathore2006

+0

所以,當它第一次渲染,然後我添加一個新的待辦事項,它工作正常。但是,當我點擊其中一個待辦事項以切換其完成狀態時,它會引發錯誤,此時this.props.todos日誌未定義。 –

回答

1

這是你所遵循的例子嗎? https://github.com/reactjs/redux/tree/master/examples/todos

不知道這是否屬於這種情況,但在您的Todo中,您可能想要刪除圍繞onClick的()

const Todo = ({ 
    onClick, 
    completed, 
    text 
}) => (
    <li onClick={ onClick } /* <- this bit */ 
    style={{textDecoration: completed ? 'line-through' : 'none'}}> 
     {text} 
    </li> 
); 
1

問題在於您的todos reducer中的「TOGGLE_TODO」情況。你有這樣的代碼:

return state.map(t => {todo(t, action)}) 

括號是不必要的,並導致箭頭函數期望返回語句。由於沒有返回語句,返回值是未定義的,所以你得到一個未定義數值的數組。

將其更改爲

return state.map(t => todo(t, action)); 
相關問題