immutable在redux中的应用主要集中在reducers中对state数据的操作上。
可以参考 stackoverflow中的问题
下面和结合一个实例关于immutable部分的介绍和注意的问题。
不使用immutable时的写法
数据结构(普通的对象数据):
const dummyTodos = [
{ id: 0, isDone: true, text: 'make components' },
{ id: 1, isDone: false, text: 'design actions' },
{ id: 2, isDone: false, text: 'implement reducer' },
{ id: 3, isDone: false, text: 'connect components' }
];
纯组件:
const Todo = ({ todo }) => {
if (todo.isDone) {
return {todo.text}
}
return {todo.text}
};
const TodoList = ({ todos }) => {
return (
{todos.map(todo => (
-
)}
);
}
这个todo app有2个主要的动作,'ADD_TODO', 'TOGGLE_TODO',下面来完成action creators,reducers等
action creators, reducers
action creators
// 产生一个随机的32位字符串
const uid = () => Math.randow().toString(34).slice(2);
const addTodo = (text) => ({
type: 'ADD_TODO',
payload: {
id: uid(),
text,
isDone: false
}
});
const toggleTodo = (id) => ({
type: 'TOGGLE_TODO',
payload: id
});
reducers 和 immutable js
在这里就涉及到数据的处理工作了,通过immutable来完成添加和更新数据。(这里actions比较少,直接将所有的actions.type都用一个reducer处理)
// 使用常用的Map, List集合
import { Map, List } from 'immutable';
# 初始化, 将初始状态变为List集合
const initState = List([]);
// 将数据解构变为immutable形式
List [
Map { id: 0, isDone: true, text: 'make components' },
Map {...},
Map {...}
...
]
const rootReducer = (state = initState, action) => {
switch (action.type) {
case 'ADD_TODO':
// 变为immutable之后,可以直接使用 'push' 来添加到数组
// 不用担心改变原来的数据
# 注意先将对象变为Map集合之后再push到 List集合中
return state.push(Map(action.payload));
case 'TOGGLE_TODO':
// 对于更新Map集合中的某个属性,使用immutable中update方法
// Map集合 update方法的其中一种形式 update(key, updater)
# 注意这里使用immutable中的'map'和'get'方法: todo.get('id')
return state.map(todo => {
if (todo.get('id') === action.payload) {
return todo.update('isDone', isDone => !isDone);
} else {
return todo;
}
});
default:
return state;
}
}
然后将逻辑写入纯组件中
const TodoList = ({ todos, toggleTodo, addTodo }) => {
const onSubmit = (e) => {
const input = e.target;
const text = input.value;
# 判断是否为 enter 键
const isEnterKey = e.which === 13;
const isLongEnough = text.length > 0;
if (isEnterKey && isLongEnough) {
addTodo(text);
input.value = '';
}
};
const toggleClick = (id) => () => toggleTodo(id);
return (
{todos.map(todo => (
-
# 注意这里要将Map集合转变为普通JS对象
))}
)
}
使用react-redux将状态和组件连接起来
import { connect } from 'react-redux';
const mapStateToProps = (state) => ({
todos: state
});
const mapDispatchToProps = (dispatch) => ({
addTodo: text => dispatch(addTodo(text)),
toggleTodo: id => dispatch(toggleTodo(id))
});
// 这相当于
dispatch(addTodo(text))}
toggleTodo={id => dispatch(toggleTodo(id))}
/>
// 使用一个容器
const TodoListContainer = connect(
mapStateToProps,
mapDispatchToProps
)(TodoList);
将store通过Provider传递下去
import { createStore } from 'redux';
import { Provider } from 'react-redux';
const store = createStore(rootReducer);
ReactDOM.render(
,
document.getElementById('root')
);
完成!
完整代码 jsbin