2017-03-02 121 views
3

我有一個關於react-redux的問題,我正在玩一些小的測試代碼,以瞭解它是如何工作的。react-redux connect不重新渲染組件,但道具得到更新

Git repository with problematic code

一切看起來正確,動作生成器,減速機,調度員,mapStateToProps和連接功能。

我也會在這裏粘貼代碼:

沒有狀態變異。

但是,當子藤傳遞給它從主(問題的組件)TodoBox(index.jsx)(index.jsx)調用函數(onClick事件),然後 1.調度員被炒魷魚 2.減速,都會激發和回報與預期的更新 3. mapStateToProps新的國家,都會激發和收益預期的結果

但TodoBox組件,請不要重新渲染 從瀏覽器控制檯,我可以看到this.props的TodoBox已更新的值。

這是怎麼回事,我不明白,檢查了很多文章和例子,但沒有匹配。

誰能檢測到問題,我需要幫助。

app.js(反應入口點)

import React from 'react'; 
 
import ReactDOM from 'react-dom'; 
 
import TodoBox from './views/index.jsx'; 
 
import { createStore } from 'redux'; 
 
import { Provider } from 'react-redux'; 
 
import * as actions from './redux_actions.js'; 
 

 
var data = JSON.parse(document.getElementById('initial-data').getAttribute('data-json')); 
 

 
const todosReducer = function (state={todos: data}, action) { 
 
    switch(action.type) { 
 
    case actions.UPDATE_TODO: 
 
     let newState = Object.assign({}, state) 
 
     let upd1 = updateRow(newState.todos, 'titel', action.todoUpdate.id, 'checked', action.todoUpdate.checked) 
 
     newState.todos = updateRow(upd1, 'titel', action.todoUpdate.id, 'detail', action.todoUpdate.checked ? 'Done' : 'Sorry not done') 
 
     return newState 
 
     break; 
 
    default: 
 
     return state; 
 
    } 
 
} 
 

 
function updateRow(tab, where, val, updfield, val2) { 
 
    tab.forEach((row) => { 
 
     row[where] === val ? row[updfield] = val2 : null 
 
    }) 
 
    return tab 
 
} 
 

 
var Store = createStore(todosReducer) 
 

 
ReactDOM.render(<Provider store={Store}><TodoBox /></Provider>, document.getElementById("app"));

index.jsx

import React from 'react'; 
 
import * as Redux from 'redux'; 
 
import { connect } from 'react-redux' 
 
import * as actions from '../redux_actions.js' 
 

 

 
class TodoBox extends React.Component { 
 
     render() { 
 
      return (
 
       <div className="todoBox"> 
 
        <h1>Todos</h1> 
 
        <TodoList data={this.props.todos} func={this.props.handleChange}/> 
 
        <TodoForm /> 
 
       </div> 
 
      ); 
 
     } 
 
    } 
 

 

 

 
class TodoList extends React.Component { 
 
    render() { 
 
    let todo = this.props.data.map((todos) => { return <Todo titel={todos.titel} func={this.props.func} check={todos.checked} key={todos.titel}>{todos.detail}</Todo> }) 
 
    return (
 
     <div className="todoList"> 
 
      <table style={{border: "2px solid black"}}> 
 
       <tbody> 
 
       {todo} 
 
       </tbody> 
 
      </table> 
 
     </div> 
 
    ); 
 
    } 
 
} 
 

 

 
class Todo extends React.Component { 
 
    render() { 
 
    return (
 
     <tr> 
 
     <td style={style.tableContent}> 
 
      <input id={this.props.titel} type="checkbox" checked={this.props.checked} onChange={this.props.func}/> 
 
     </td> 
 
     <td style={style.tableContent}>{this.props.titel}</td> 
 
     <td style={style.tableContent}>{this.props.children}</td> 
 
     </tr> 
 
    ); 
 
    } 
 
} 
 

 

 
Todo.propTypes = { 
 
    titel: React.PropTypes.string.isRequired 
 
} 
 

 

 
class TodoForm extends React.Component { 
 
    render() { 
 
    return (
 
     <div className="todoForm"> 
 
     I am a TodoForm. 
 
     </div> 
 
    ); 
 
    } 
 
} 
 

 
let style = { 
 
     tableContent: { 
 
      border: "1px solid black" 
 
     } 
 
    }; 
 

 

 
const mapStateToProps = function (state) { 
 
    return { todos: state.todos } 
 
} 
 

 
const mapDispatchToProps = function(dispatch) { 
 
    return { 
 
    handleChange: function(event) { 
 
     dispatch(actions.actionUpdateTodo({id: event.target.id, checked: event.target.checked})); 
 
    } 
 
    } 
 
} 
 

 
export default connect(mapStateToProps, mapDispatchToProps)(TodoBox)

redux_actions.jsx

export const UPDATE_TODO = 'UPDATE_TODO' 
 

 
export function actionUpdateTodo(todoUpdate) { 
 
    return { type: UPDATE_TODO, todoUpdate: todoUpdate } 
 
}

回答

0

請檢查http://redux.js.org/docs/Troubleshooting.html

看來你是變異的商店。問題在於你的減速器。

我強烈建議您閱讀pure functions

const todosReducer = function (state={todos: data}, action) { 
    switch(action.type) { 
    case actions.UPDATE_TODO: 
     let newState = Object.assign({}, state) 
     let upd1 = updateRow(newState.todos, 'titel', action.todoUpdate.id, 'checked', action.todoUpdate.checked) 
     newState.todos = {...updateRow(upd1, 'titel', action.todoUpdate.id, 'detail', action.todoUpdate.checked ? 'Done' : 'Sorry not done')} //should do the trick. Although I would strongly suggest you to refactor the updateRow function. 
     return newState //even so you are returning a newState, the reference value (todos) is not a new instance. 
     break; 
    default: 
     return state; 
    } 
} 

function updateRow(tab, where, val, updfield, val2) { 
    tab.forEach((row) => { 
     row[where] === val ? row[updfield] = val2 : null 
    }) 
    return tab 
} 
+0

謝謝你的回答!我認爲'讓newState = Object.assign({},state)'創建全部新對象和所有內容。其實我不明白它爲什麼會發生變異。使用擴展運算符它沒有工作,但下一個建設工作'newState.todos = Object.assign([],updateRow(upd1,'titel',action.todoUpdate.id,'detail',action.todoUpdate.checked?'Done ':'對不起'))' – sigvamo

相關問題