redux学习笔记

redux笔记

redux用来管理state
action→state
reducer将action与state串起来。
例如
function visibilityFilter(state = ‘SHOW_ALL’, action) {
if (action.type === ‘SET_VISIBILITY_FILTER’) {
return action.filter;
} else {
return state;
}
}

function todos(state = [], action) {
switch (action.type) {
case 'ADD_TODO':
    return state.concat([{ text: action.text, completed: false }]);
case 'TOGGLE_TODO':
    return state.map((todo, index) =>
    action.index === index ?
        { text: todo.text, completed: !todo.completed } :
        todo
)
default:
    return state;
}
}

再开发一个 reducer 调用这两个 reducer,进而来管理整个应用的 state:

function todoApp(state = {}, action) {
return {
    todos: todos(state.todos, action),
    visibilityFilter: visibilityFilter(state.visibilityFilter, action)
};
}

三大原则

  • 单一数据源
  • state只读
  • 使用纯函数来执行修改

数组型state

state只读:reducer中返回新的state时只能返回一个新的而不是修改原state,对于数组型的state可以使用concat()或者slice()创建一个新的数组,例:

const todos = [
'Go to the store',
'Clean the house',
'Cook dinner',
'Learn to code',
];
const immutableReducer = (state = todos, action) => {
switch(action.type) {
    case ADD_TO_DO:
    // 不要在这里改变 state
    return state.concat(action.todo)
    default:
    return state;
}
};

或者ES6的新解决办法,扩展运算符:let newArray = [...myArray];此时newArray是myArray的一个新的复制,如果想要添加新的元素可以[... myArray,'new value'],删出数组元素使用slice:

    return [
        ...state.slice(0, action.index),
        ...state.slice(action.index + 1, state.length)
    ];

删除数组下标为index的元素

对象型state

对于state为对象时,使用Object.assign()

const defaultState = {
status: 'offline',
community: 'freeCodeCamp'
};

const immutableReducer = (state = defaultState, action) => {
switch(action.type) {
    case 'ONLINE':
    // 不要在这里改变 state 否则测试会失败。
    return Object.assign({}, state, { status: "online" });
    default:
    return state;
}
};

const wakeUp = () => {
return {
    type: 'ONLINE'
}
};

const store = Redux.createStore(immutableReducer);

store,action,reducer

Redux store 是应用程序状态的唯一真实来源。

Redux 是一个状态管理框架,更新状态是其核心任务之一
在 Redux 中,所有状态更新都由 dispatch action 触发,action 只是一个 JavaScript 对象,其中包含有关已发生的 action 事件的信息
Redux store 接收这些 action 对象,然后更新相应的状态。有时,Redux action 也会携带一些数据。
创建 action 后要将 action 发送到 Redux store,以便它可以更新其状态,action creator 只是一个返回动作的 JavaScript 函数,换句话说,action creator 创建表示动作事件的对象

store.dispatch()讲action creator与store联系起来 例:

const store = Redux.createStore(
(state = {login: false}) => state
);

const loginAction = () => {
return {
    type: 'LOGIN'
}
};

// 在这里 dispatch action
store.dispatch(loginAction())

reducer函数:在一个 action 被创建并 dispatch 之后,Redux store 需要知道如何响应该操作
reducer将state和action作为参数,并且它总是返回一个新的state。
例子:

const defaultState = {
login: false
};

const reducer = (state = defaultState, action) => {
// 修改此行下方的代码
if (action.type=='LOGIN') {
    return {
    login:true
    }
} else return defaultState
// 修改此行上方的代码
};

const store = Redux.createStore(reducer);

const loginAction = () => {
return {
    type: 'LOGIN'
}
};//这是action creator
store.dispatch(loginAction()) //通过dispatch将store与action联系起来,通过createStore创建store与reducer的联系  

store dispatch分发action动作,reducer说明action完成了什么动作,createStore吧动作放在这个store里

传递参数

const ADD_NOTE = "ADD_NOTE";

const notesReducer = (state = "Initial State", action) => {
switch (action.type) {
    // change code below this line

    case ADD_NOTE:
    return action.text;

    // change code above this line
    default:
    return state;
}
};

const addNoteText = note => {
// change code below this line

return {
    type: ADD_NOTE,
    text: note
};

// change code above this line
};

const store = Redux.createStore(notesReducer);

console.log(store.getState());
store.dispatch(addNoteText("Hello!"));
console.log(store.getState());

组合多个reducer

需要一个rootreducer来装下小的reducer,combineReducers()

const INCREMENT = 'INCREMENT';
const DECREMENT = 'DECREMENT';

const counterReducer = (state = 0, action) => {
switch(action.type) {
    case INCREMENT:
    return state + 1;
    case DECREMENT:
    return state - 1;
    default:
    return state;
}
};

const LOGIN = 'LOGIN';
const LOGOUT = 'LOGOUT';

const authReducer = (state = {authenticated: false}, action) => {
switch(action.type) {
    case LOGIN:
    return {
        authenticated: true
    }
    case LOGOUT:
    return {
        authenticated: false
    }
    default:
    return state;
}
};

const rootReducer = Redux.combineReducers({
count: counterReducer,
auth: authReducer
});
const store = Redux.createStore(rootReducer);

异步

Redux Thunk中间件
如果要使用 Redux Thunk 中间件,请将其作为参数传递给Redux.applyMiddleware()。然后将此函数作为第二个可选参数提供给createStore()函数,然后,要创建一个异步的 action,你需要在 action creator 中返回一个以dispatch为参数的函数。在这个函数中,你可以 dispatch action 并执行异步请求。

const REQUESTING_DATA = 'REQUESTING_DATA'
const RECEIVED_DATA = 'RECEIVED_DATA'

const requestingData = () => { return {type: REQUESTING_DATA} }
const receivedData = (data) => { return {type: RECEIVED_DATA, users: data.users} }

const handleAsync = () => {
return function(dispatch) {
    // 在这里 dispatch 请求的 action

    setTimeout(function() {
    let data = {
        users: ['Jeff', 'William', 'Alice']
    }
    // 在这里 dispatch 接收到的数据 action

    }, 2500);
}
};

const defaultState = {
fetching: false,
users: []
};

const asyncDataReducer = (state = defaultState, action) => {
switch(action.type) {
    case REQUESTING_DATA:
    return {
        fetching: true,
        users: []
    }
    case RECEIVED_DATA:
    return {
        fetching: false,
        users: action.users
    }
    default:
    return state;
}
};

const store = Redux.createStore(
asyncDataReducer,
Redux.applyMiddleware(ReduxThunk.default)
);

简单解释就是,异步请求分为了两个action。一是提出数据申请requesting,二十数据receive,将这两个动作作为修改state的action。分别处理。

计数器

const INCREMENT = "INCREMENT"; // define a constant for increment action types
const DECREMENT = "DECREMENT"; // define a constant for decrement action types

// define the counter reducer which will increment or decrement the state based on the action it receives
const counterReducer = (state = 0, action) => {
switch (action.type) {
    case INCREMENT:
    return state + 1;

    case DECREMENT:
    return state - 1;

    default:
    return state;
}
};

// define an action creator for incrementing
const incAction = () => {
return {
    type: INCREMENT
};
};

// define an action creator for decrementing
const decAction = () => {
return {
    type: DECREMENT
};
};

// define the Redux store here, passing in your reducers
const store = Redux.createStore(counterReducer);

redux-react

React Redux 提供的 API 有两个关键的功能:Provider和connect

Provider需要两个 props:Redux store 和 APP 应用的子组件。用于 APP 组件的Provider可这样定义:

<Provider store={store}>
<App/>
</Provider>

连接redux与react:connect

const addMessage = (message) => {
return {
    type: 'ADD',
    message: message
}
};

const mapStateToProps = (state) => {
return {
    messages: state
}
};

const mapDispatchToProps = (dispatch) => {
return {
    submitNewMessage: (message) => {
    dispatch(addMessage(message));
    }
}
};

class Presentational extends React.Component {
constructor(props) {
    super(props);
}
render() {
    return <h3>This is a Presentational Component</h3>
}
};

const connect = ReactRedux.connect;
// 请在本行以下添加你的代码
const ConnectedComponent=connect(mapStateToProps, mapDispatchToProps)(Presentational)

上面这段代码中mapDispatchToProps负责分发action,mapStateToProps负责映射state,connect函数负责将组件与前面两者联系起来
连接到 Redux 的组件命名为Presentational,这个命名不是任意的,这样的术语通常是指未直接连接到 Redux 的 React 组件,他们只负责执行接收 props 的函数来实现 UI 的呈现。

以下折叠为将react与redux联系起来的代码

// Redux:
const ADD = 'ADD';

const addMessage = (message) => {
return {
    type: ADD,
    message: message
}
};

const messageReducer = (state = [], action) => {
switch (action.type) {
    case ADD:
    return [
        ...state,
        action.message
    ];
    default:
    return state;
}
};

const store = Redux.createStore(messageReducer);

// React:
const Provider = ReactRedux.Provider;
const connect = ReactRedux.connect;

// 请在本行以下添加你的代码
class Presentational extends React.Component {
constructor(props) {
    super(props);
    this.state = {
    input: '',
    }
    this.handleChange = this.handleChange.bind(this);
    this.submitMessage = this.submitMessage.bind(this);
}
handleChange(event) {
    this.setState({
    input: event.target.value
    });
}
submitMessage() {
    this.props.submitNewMessage(this.state.input)
    this.setState({
    input: '',
    });
}
render() {
    return (
    <div>
        <h2>Type in a new Message:</h2>
        <input
        value={this.state.input}
        onChange={this.handleChange}/><br/>
        <button onClick={this.submitMessage}>Submit</button>
        <ul>
        {this.props.messages.map( (message, idx) => {
            return (
                <li key={idx}>{message}</li>
            )
            })
        }
        </ul>
    </div>
    );
}
};
// 请在本行以上添加你的代码

const mapStateToProps = (state) => {
return {messages: state}
};

const mapDispatchToProps = (dispatch) => {
return {
    submitNewMessage: (message) => {
    dispatch(addMessage(message))
    }
}
};

const Container = connect(mapStateToProps, mapDispatchToProps)(Presentational);

class AppWrapper extends React.Component {
render() {
    return (
    <Provider store={store}>
        <Container/>
    </Provider>
    );
}
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值