2016-12-07 15 views
8

Tôi có danh sách cần làm và muốn đặt trạng thái của mục đó trong mảng thành "hoàn thành" nếu người dùng nhấp vào "hoàn tất".Cập nhật giá trị đơn lẻ trong mảng mục | phản ứng redux

Đây là hành động của tôi:

export function completeTodo(id) { 
    return { 
     type: "COMPLETE_TASK", 
     completed: true, 
     id 
    } 
} 

Đây là giảm tốc của tôi:

case "COMPLETE_TASK": { 
      return {...state, 
       todos: [{ 
        completed: action.completed 
       }] 
      } 
     } 

Vấn đề tôi đang gặp là trạng thái mới nào không còn có các văn bản liên quan đến các mục đó todo trên mục đã chọn và ID không còn ở đó nữa. Đây có phải là vì tôi đang ghi đè tiểu bang và bỏ qua các thuộc tính trước đó không? Mục đối tượng tải của tôi trông giống như sau:

Objecttodos: Array[1] 
    0: Object 
     completed: false 
     id: 0 
     text: "Initial todo" 
    __proto__: Object 
    length: 1 
    __proto__: Array[0] 
    __proto__: Object 

Như bạn có thể thấy, tất cả những gì tôi muốn làm là đặt giá trị hoàn thành thành true.

Trả lời

29

Bạn cần chuyển đổi mảng todos để cập nhật mục thích hợp. Array.map là cách đơn giản nhất để thực hiện việc này:

case "COMPLETE_TASK": 
    return { 
     ...state, 
     todos: state.todos.map(todo => todo.id === action.id ? 
      // transform the one with a matching id 
      { ...todo, completed: action.completed } : 
      // otherwise return original todo 
      todo 
     ) 
    }; 

Có thư viện để giúp bạn cập nhật trạng thái sâu này. Bạn có thể tìm thấy một danh sách các thư viện như vậy ở đây: https://github.com/markerikson/redux-ecosystem-links/blob/master/immutable-data.md#immutable-update-utilities

Cá nhân, tôi sử dụng ImmutableJS (https://facebook.github.io/immutable-js/) mà giải quyết vấn đề với updateInsetIn của phương pháp (mà là hiệu quả hơn so với đối tượng bình thường và mảng cho các đối tượng lớn với rất nhiều phím và đối với mảng, nhưng chậm hơn đối với mảng nhỏ).

+0

Cảm ơn sự giúp đỡ của bạn TomW và cảm ơn bạn đã tham khảo thư viện về cập nhật trạng thái sâu. Giúp đỡ nhiều! – Filth

+0

Tôi thấy bạn đang sử dụng một dòng nếu tuyên bố mặc dù tôi thấy nó khó đọc. Tôi biết giảm bom khi có báo cáo. Bạn có thể giải thích những gì đang xảy ra ở đây và có thể một cách khác để viết logic này? – Filth

+0

Giảm thiểu bom 'khi bạn không trả lại trạng thái từ mọi nhánh - 'if' phát biểu là tốt, bạn chỉ cần đảm bảo rằng bạn' trở về trạng thái '; sau 'if'. Nếu bạn nhìn vào trình xử lý TOGGLE_TODO ngay dưới đây: http://redux.js.org/docs/basics/Reducers.html#handling-more-actions bạn sẽ thấy một ví dụ rất giống với ví dụ của tôi sử dụng 'if' câu lệnh thay vì một '?:' - '?:' có một lợi ích nhỏ so với câu lệnh if ở chỗ nó buộc bạn trả về một giá trị từ mỗi nhánh. – TomW

1

New trạng thái không không còn có các văn bản liên quan đến các mục đó todo trên mục đã chọn và ID không còn ở đó, Đây có phải là vì tôi ghi đè lên nhà nước và bỏ qua các thuộc tính trước đó?

Vâng, bởi vì trong mỗi lần cập nhật bạn đang gán một mảng mới với chỉ có một chính completed, và mảng mà không chứa bất kỳ giá trị trước đó. Vì vậy, sau khi cập nhật mảng sẽ không có dữ liệu trước đó. Đó là lý do tại sao văn bản và id không có ở đó sau khi cập nhật.

Giải pháp:

1- Sử dụng array.map để tìm các yếu tố đúng thì cập nhật giá trị, Như thế này:

case "COMPLETE_TASK": 
    return { 
     ...state, 
     todos: state.todos.map(todo => 
      todo.id === action.id ? { ...todo, completed: action.completed } : todo 
     ) 
    }; 

2- Sử dụng array.findIndex để tìm ra chỉ số của đối tượng đặc biệt sau đó cập nhật điều đó, như sau:

case "COMPLETE_TASK": 
    let index = state.todos.findIndex(todo => todo.id === action.id); 
    let todos = [...todos]; 
    todos[index] = {...todos, completed: action.completed}; 
    return {...state, todos} 

Kiểm tra đoạn này, bạn sẽ nhận được một ý tưởng tốt hơn về những sai lầm bạn đang làm:

let state = { 
 
    a: 1, 
 
    arr: [ 
 
    {text:1, id:1, completed: true}, 
 
    {text:2, id:2, completed: false} 
 
    ] 
 
} 
 

 
console.log('old values', JSON.stringify(state)); 
 

 
// updating the values 
 

 
let newState = { 
 
    ...state, 
 
    arr: [{completed: true}] 
 
} 
 

 
console.log('new state = ', newState);

0

Một trong những nguyên tắc thiết kế tinh trong Phản ứng được "Đừng biến nhà nước."Nếu bạn muốn thay đổi dữ liệu trong một mảng, bạn muốn tạo một mảng mới với (các) giá trị đã thay đổi.

Ví dụ, tôi có một loạt các kết quả trong trạng thái. 0 cho mỗi chỉ số trong hàm dựng của tôi

this.state = {   
     index:0, 
     question: this.props.test[0].questions[0], 
     results:[[0,0],[1,0],[2,0],[3,0],[4,0],[5,0]], 
     complete: false   
}; 

Sau này, tôi không thay đổi giá trị trong mảng .Tôi có thể sử dụng toán tử spread. Phương thức mảng mảng trả về một mảng mới, nó sẽ không thay đổi mảng hiện có.

updateArray = (list, index,score) => { 
    // updates the results array without mutating it 
     return [ 
     ...list.slice(0, index), 
     list[index][1] = score, 
     ...list.slice(index + 1) 
    ]; 
}; 

Khi tôi wan Để cập nhật một mục trong mảng, tôi gọi updateArray và đặt trạng thái trong một lần:

this.setState({ 
     index:newIndex, 
     question:this.props.test[0].questions[newIndex], 
     results:this.updateArray(this.state.results, index, score) 
}); 
Các vấn đề liên quan