We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
There was an error while loading. Please reload this page.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
redux和mobx一样也是集中式状态管理。有3个关键概念。
项目的入口文件
import React from 'react' import { render } from 'react-dom' import { Provider } from 'react-redux' import { createStore } from 'redux' import todoApp from './reducers' import App from './components/App' let store = createStore(todoApp) render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') )
actions/index.js
生成action对象的工厂函数文件。其实不写这个直接在dispatch的时候store.dispatch({type: 'ADD', id: xxx,text:xxx})也可以。
let nextTodoId = 0 export const addTodo = text => { return { type: 'ADD_TODO', id: nextTodoId++, text } } export const setVisibilityFilter = filter => { return { type: 'SET_VISIBILITY_FILTER', filter } } export const toggleTodo = id => { return { type: 'TOGGLE_TODO', id } }
reducers/todos.js
const todos = (state = [], action) => { switch (action.type) { case 'ADD_TODO': return [ ...state, { id: action.id, text: action.text, completed: false } ] case 'TOGGLE_TODO': return state.map(todo => (todo.id === action.id) ? {...todo, completed: !todo.completed} : todo ) default: return state } } export default todos
reducers/visibilityFilter.js
const visibilityFilter = (state = 'SHOW_ALL', action) => { switch (action.type) { case 'SET_VISIBILITY_FILTER': return action.filter default: return state } } export default visibilityFilter
reducers/index.js
combineReducers合并所有reducer。
import { combineReducers } from 'redux' import todos from './todos' import visibilityFilter from './visibilityFilter' const todoApp = combineReducers({ todos, visibilityFilter }) export default todoApp
redux中有有一个重要的概念就是容器组件和UI组件。容器组件负责和操作state,dispatch action。而UI组件被容器组件包裹,容器组件以props的方式给UI组件传递 state和dispatch操作函数。这种分离的做法会让UI组件更加纯粹,能够实现低耦合,高复用。
components/TodoList.js
import React from 'react' import PropTypes from 'prop-types' import Todo from './Todo' const TodoList = ({ todos, onTodoClick }) => ( <ul> {todos.map(todo => ( <Todo key={todo.id} {...todo} onClick={() => onTodoClick(todo.id)} /> ))} </ul> ) TodoList.propTypes = { todos: PropTypes.arrayOf( PropTypes.shape({ id: PropTypes.number.isRequired, completed: PropTypes.bool.isRequired, text: PropTypes.string.isRequired }).isRequired ).isRequired, onTodoClick: PropTypes.func.isRequired } export default TodoList
react-rudex是一个用来连接UI组件和容器组件的工具,使用connect方法。
connect(mapstatetoprops, mapdispatchtoprops)(component),返回容器组件。这个方法会把定义的UI组件所需的state属性和定义好的dispatch方法挂载到UI组件的props属性上。UI组件直接通过props属性调用相应的数据和方法。
containers/VisibleTodoList.js
import { connect } from 'react-redux' import { toggleTodo } from '../actions' import TodoList from '../components/TodoList' const getVisibleTodos = (todos, filter) => { switch (filter) { case 'SHOW_COMPLETED': return todos.filter(t => t.completed) case 'SHOW_ACTIVE': return todos.filter(t => !t.completed) case 'SHOW_ALL': default: return todos } } const mapStateToProps = state => { return { todos: getVisibleTodos(state.todos, state.visibilityFilter) } } const mapDispatchToProps = dispatch => { return { onTodoClick: id => { dispatch(toggleTodo(id)) } } } const VisibleTodoList = connect( mapStateToProps, mapDispatchToProps )(TodoList) export default VisibleTodoList
前面介绍的都是同步示例,redux还可以处理异步数据流。前面介绍过reducer是纯函数,接收相同的输入产生相同的输出,那异步操作肯定不能在reducer中执行。redux设计的方案是在action中执行异步操作,也就是定义异步action,在异步action中还能调用同步action。因此异步action不需要生成action对象,而是返回函数,直接在action中定义异步操作,不需要再经过reducer。
存在的问题:
解决方法:
createStore可以配置第二个参数,applyMiddleware表示启用中间件,让dispatch可以接收action函数
redux-thunk中的thunkMiddleware,会在action返回的函数中自动带上dispatch参数。
actions.js
import fetch from 'cross-fetch' export const REQUEST_POSTS = 'REQUEST_POSTS' function requestPosts(subreddit) { return { type: REQUEST_POSTS, subreddit } } export const RECEIVE_POSTS = 'RECEIVE_POSTS' function receivePosts(subreddit, json) { return { type: RECEIVE_POSTS, subreddit, posts: json.data.children.map(child => child.data), receivedAt: Date.now() } } export const INVALIDATE_SUBREDDIT = ‘INVALIDATE_SUBREDDIT’ export function invalidateSubreddit(subreddit) { return { type: INVALIDATE_SUBREDDIT, subreddit } } // 来看一下我们写的第一个 thunk action 创建函数! // 虽然内部操作不同,你可以像其它 action 创建函数 一样使用它: // store.dispatch(fetchPosts('reactjs')) export function fetchPosts(subreddit) { // Thunk middleware 知道如何处理函数。 // 这里把 dispatch 方法通过参数的形式传给函数, // 以此来让它自己也能 dispatch action。 return function (dispatch) { // 首次 dispatch:更新应用的 state 来通知 // API 请求发起了。 dispatch(requestPosts(subreddit)) // thunk middleware 调用的函数可以有返回值, // 它会被当作 dispatch 方法的返回值传递。 // 这个案例中,我们返回一个等待处理的 promise。 // 这并不是 redux middleware 所必须的,但这对于我们而言很方便。 return fetch(`http://www.subreddit.com/r/${subreddit}.json`) .then( response => response.json(), // 不要使用 catch,因为会捕获 // 在 dispatch 和渲染中出现的任何错误, // 导致 'Unexpected batch number' 错误。 // https://github.com/facebook/react/issues/6895 error => console.log('An error occurred.', error) ) .then(json => // 可以多次 dispatch! // 这里,使用 API 请求结果来更新应用的 state。 dispatch(receivePosts(subreddit, json)) ) } }
index.js
import thunkMiddleware from 'redux-thunk' import { createLogger } from 'redux-logger' import { createStore, applyMiddleware } from 'redux' import { selectSubreddit, fetchPosts } from './actions' import rootReducer from './reducers' const loggerMiddleware = createLogger() const store = createStore( rootReducer, applyMiddleware( thunkMiddleware, // 允许我们 dispatch() 函数 loggerMiddleware // 一个很便捷的 middleware,用来打印 action 日志 ) ) store.dispatch(selectSubreddit('reactjs')) store .dispatch(fetchPosts('reactjs')) .then(() => console.log(store.getState()) )
The text was updated successfully, but these errors were encountered:
No branches or pull requests
redux
redux和mobx一样也是集中式状态管理。有3个关键概念。
基础应用
入口文件(index.jsx):
项目的入口文件
创建Action(
actions/index.js
):生成action对象的工厂函数文件。其实不写这个直接在dispatch的时候store.dispatch({type: 'ADD', id: xxx,text:xxx})也可以。
Reducers:
reducers/todos.js
)reducers/visibilityFilter.js
reducers/index.js
combineReducers合并所有reducer。
UI组件
redux中有有一个重要的概念就是容器组件和UI组件。容器组件负责和操作state,dispatch action。而UI组件被容器组件包裹,容器组件以props的方式给UI组件传递 state和dispatch操作函数。这种分离的做法会让UI组件更加纯粹,能够实现低耦合,高复用。
components/TodoList.js
容器组件
react-rudex是一个用来连接UI组件和容器组件的工具,使用connect方法。
connect(mapstatetoprops, mapdispatchtoprops)(component),返回容器组件。这个方法会把定义的UI组件所需的state属性和定义好的dispatch方法挂载到UI组件的props属性上。UI组件直接通过props属性调用相应的数据和方法。
containers/VisibleTodoList.js
异步Action
前面介绍的都是同步示例,redux还可以处理异步数据流。前面介绍过reducer是纯函数,接收相同的输入产生相同的输出,那异步操作肯定不能在reducer中执行。redux设计的方案是在action中执行异步操作,也就是定义异步action,在异步action中还能调用同步action。因此异步action不需要生成action对象,而是返回函数,直接在action中定义异步操作,不需要再经过reducer。
存在的问题:
解决方法:
createStore可以配置第二个参数,applyMiddleware表示启用中间件,让dispatch可以接收action函数
redux-thunk中的thunkMiddleware,会在action返回的函数中自动带上dispatch参数。
actions.js
index.js
The text was updated successfully, but these errors were encountered: