React & Redux
一、什么是Redux
Redux即类Flux的脚本库, 但是它不完全是Flux(Flux是真的繁琐),它包含Action、Action生成器、Store,以及用于修改State的Action对象。
1)State
在我们不知道Flux和Redux之前,我们想要操作与管理State一般有两种选择:
1、每个组件单独管理自己的State。
2、由根节点统一管理,向下传递State。
这两种方式所暴露出的缺点很明显:
第一种:State管理杂乱无章,逻辑不清晰,不易于维护。
第二种:增加代码的逻辑复杂度,增加维护成本。
Flux和Redux的出现就帮我们完美解决了这些痛点。两者都推荐将State存放尽可能少的几个对象中,这样就降低了我们去维护State的成本,可以将更多的精力放在UI与业务上。
2)Action
Redux有一个非常重要的规则,应用程序的State应该存放在单个不可变对象中!(State对象无法变更)
Action是更新Redux应用程序State的唯一方式。Action为我们提供了应该变更哪些内容的指令,说简单点就是我们想让State怎么变化。
3)Reducer
当我们使用Redux来管理State的时候,我们整个State树都是存储在单个对象中的。一个潜在的问题可能是它的模块化程度不够(如果丧失了模块化的优势,那我就可能放弃学习与使用React了,哈哈。)。Redux是通过函数进行模块化的,他们用来更新指定的State树中的内容,这些函数就被称为Reducer。
3)Store
Store就是保存应用程序State数据和处理所有State更新的地方。
Store通过将当前的State和Action传递给单个Reducer来进行State更新。
4)Action生成器
这个确实没什么说的,Action生成器就是对我们传递的Action参数的一个方法封装,易于使用和维护。
代码
Action & Action生成器
import Constants from "../Constants";
import {v4} from "uuid";
export const AddItem = title => {
return {
type: Constants.ADD_ITEM,
id: v4(),
title
}
}
export const RemoveItem = id => {
return {
type: Constants.REMOVE_ITEM,
id
}
}
Reducer
import Constants from "../Constants";
const item = (state = {}, action) => {
switch (action.type) {
case Constants.ADD_ITEM :
return {
id: action.id,
title: action.title
};
default :
return state;
}
}
export const items = (state = [], action) => {
switch (action.type) {
case Constants.ADD_ITEM :
return [
...state,
item({}, action)
];
case Constants.REMOVE_ITEM :
return state.filter(i =>
i.id !== action.id
)
default :
return state;
}
}
Store
import {createStore, combineReducers} from "redux";
import {items} from "./chapter8-test/reducers";
const store = createStore(combineReducers({items}));
export default store;
Demo代码
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from "./chapter8-test/App";
import store from "./chapter8-test/store";
ReactDOM.render(
<App store={store}/>,
document.getElementById('root')
)
App.js
import React from 'react';
import PropTypes from 'prop-types';
import ItemList from './ItemList';
import AddItemForm from "./AddItemForm";
class App extends React.Component {
static propTypes = {
store: PropTypes.object.isRequired
}
static childContextTypes = {
store: PropTypes.object.isRequired
}
getChildContext() {
return {
store: this.props.store
}
}
componentWillMount() {
const { store } = this.props;
this.unSubscribe = store.subscribe(
() => this.forceUpdate()
);
}
componentWillUnmount() {
this.unSubscribe();
}
render() {
return (
<div>
<AddItemForm/>
<ItemList/>
</div>
)
}
}
export default App;
AddItemForm.js
import React from 'react';
import PropTypes from 'prop-types';
import {AddItem} from './actions'
const AddItemForm = (props, {store}) => {
let title;
const submit = e => {
e.preventDefault();
let addItem = AddItem(title.value);
store.dispatch(addItem);
title.value = '';
title.focus();
}
return (
<form onSubmit={submit}>
<input type="text"
ref={input => title = input}
required/>
<button>ADD</button>
</form>
)
}
AddItemForm.contextTypes = {
store: PropTypes.object
}
export default AddItemForm;
ItemList.js
import React from 'react';
import PropTypes from 'prop-types';
import Item from "./Item";
const ItemList = (props, {store}) => {
const {items} = store.getState();
return (
<ul>
{items.length === 0 ?
<span>No Item List. (Add a Item)</span> :
items.map((item, index) =>
<Item key={item.id}
{...item}
/>
)
}
</ul>
)
}
ItemList.contextTypes = {
store: PropTypes.object
}
export default ItemList;
Item.js
import React from 'react';
import PropTypes from 'prop-types';
import {RemoveItem} from "./actions";
const Item = (props, {store}) => {
const {id, title} = props;
return (
<li>
{title}
<button onClick={() => store.dispatch(RemoveItem(id))}>X</button>
</li>
)
}
Item.contextTypes = {
store: PropTypes.object
}
export default Item;
Constants.js
const Constants = {
ADD_ITEM: "ADD_ITEM",
REMOVE_ITEM: "REMOVE_ITEM"
}
export default Constants;
撒花完结
- 水平有限
- 能力有限
- 忘各位大佬勿喷
- 个人实属太懒,不想写太多字,见谅,见谅