demo地址:
git clone https://github.com/reactjs/redux.git
cd redux/examples/todos
npm install
npm start
3.第一部分(如图)
1.入口文件index.js
import React from 'react'
import { render } from 'react-dom'
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import App from './components/App'
import rootReducer from './reducers'
const store = createStore(rootReducer)
render(
,
document.getElementById('root')
)
Provider作用:将store传给组件,与connect配合使用,connect则是将组件与redux关联起来。本质上 Provider 就是给 connect 提供 store 用的。(react-redux提供)
2.组件入口App.js
import React from 'react';
import AddTodo from '../containers/AddTodo'
import VisibleTodoList from '../containers/VisibleTodoList'
// 使用jsx写法一定要引入react,不然会报错:'React' must be in scope when using JSX react/react-in-jsx-scope
const App = () => {
return (
)
}
export default App;
3.AddTodo 的action以及reducer
//action.js
let nextTodoId = 0;
export const addTodo = (text) => {
return {
type: 'ADD_TODO',
//id存在的意义是作为key
id: nextTodoId++,
text
}
}
//reducer
const todos = (state = [], action) => {
switch (action.type) {
case 'ADD_TODO':
return [
...state,
{
id: action.id,
text: action.text,
completed: false
}
]
default:
return state
}
}
export default todos
上面我们已经将reducer作为参数传入了store,所以只要触发dipatch,就会根据type做出相应的更新。
...state解构写法,一定要给state一个默认值,不然会报错。
4.组件AddTodo.js
import React from 'react'
import { addTodo } from '../actions'
import { connect } from 'react-redux'
//{dispatch}解构写法,也可以写成任意一个变量名,比如a,获取dipatch:a.dipatch
const AddTodo = ({ dispatch }) => {
let input;
return (
)
}
export default connect()(AddTodo)
action和reducer之间能联系起来的关键是connect,connect将store和组件联系起来,即connect连接视图和数据层。通过provider把store绑定在组件上(provider为connect提供了store),当dispatch 的时候,会更新相对应type的store数据 。(有点乱,对于connect的具体解析可参考https://www.jianshu.com/p/9873d4ccb891(关于react-redux中的connect用法介绍及原理解析))
5.VisibleTodoList.js
import { connect } from 'react-redux'
import TodoList from '../components/TodoList'
const getVisibleTodos = (todos) => {
console.log(todos)
return todos
}
const mapStateToProps = state => ({
todos: getVisibleTodos(state.todos)
})
export default connect(
mapStateToProps
)(TodoList)
connect的个人总结:
- connect 连接组件和store
- connect([mapStateToProps], [mapDispatchToProps], [mergeProps],[options])
- mapStateToProps: mapStateToProps(state,ownProps):stateProps,将store中的数据作为props绑定到组件上
- mapDispatchToProps(dipatch,ownProps):dispatchProps,将action作为props绑定到组件上
第二部分(如图)
1.actions 和reducers
//actions
export const VisibilityFilters = {
SHOW_ALL: 'SHOW_ALL',
SHOW_COMPLETED: 'SHOW_COMLETED',
SHOW_ACTIVE: 'SHOW_ACTIVE'
}
export const toggleTodo = (id) => (
{
type: 'TOGGLE_TODO',
id
}
)
VisibilityFilters是用来判断三种列表显示状态。SHOW_ALL显示全部,SHOW_COMPLETED显示已完成的,SHOW_ACTIVE显示正在进行的
//reducers
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
2.组件
TodoList.js
import React from 'react'
import Todo from './Todo'
const TodoList = ({ todos, toggleTodo }) => (
{todos.map(todo =>
toggleTodo(todo.id)}
/>
)}
)
export default TodoList
Todo.js
import React from 'react'
const Todo = ({ onClick, completed, text }) => (
{text}
)
export default Todo
这部分的重点
import { connect } from 'react-redux'
import { toggleTodo, VisibilityFilters } from '../actions'
import TodoList from '../components/TodoList'
const getVisibleTodos = (todos, filter) => {
switch (filter) {
case VisibilityFilters.SHOW_ALL:
return todos
case VisibilityFilters.SHOW_COMPLETED:
return todos.filter(t => t.completed)
case VisibilityFilters.SHOW_ACTIVE:
return todos.filter(t => !t.completed)
default:
throw new Error('Unknown filter: ' + filter)
}
}
const mapStateToProps = state => ({
todos: getVisibleTodos(state.todos, state.visibilityFilter)
})
const mapDispatchToProps = dispatch => ({
toggleTodo: id => dispatch(toggleTodo(id))
})
export default connect(
mapStateToProps,
mapDispatchToProps
)(TodoList)
我的理解:
通过connect把组件与store建立起联系。
传入的第一个参数mapStateToProps,我们将store中的数据作为props绑定到组件中,所以这里我们能拿得到state。
传入的第二个参数mapDispatchToProps,参数是dispatch,则是我们将action作为props绑定到组件中,所以当我们点击todoList 的时候,就会触发dispatch,返回包含对应action的object对象。
回到todoList:todoList的两个参数{todos,toggleTodo}就是这样获取的。通过解构在Todo中拿到了action对应的两个参数{completed,text}
第三部分(如图)
1.actions和reudcers
//actions
export const setVisibilityFilter = filter => ({
type: 'SET_VISIBILITY_FILTER',
filter
})
说明:filter是组件传进来的参数,区分三种情况
//reducers
import { VisibilityFilters } from '../actions'
const visibilityFilter = (state = VisibilityFilters.SHOW_ALL, action) => {
switch (action.type) {
case 'SET_VISIBILITY_FILTER':
return action.filter
default:
return state
}
}
export default visibilityFilter
2.组件
最里层组件
import React from 'react'
const Link = ({ active, children, onClick }) => (
)
export default Link
这边的参数可以先不看,假设是三个button
import { connect } from 'react-redux'
import { setVisibilityFilter } from '../actions'
import Link from '../components/Link'
const mapStateToProps = (state, ownProps) => ({
active: ownProps.filter === state.visibilityFilter
})
const mapDispatchToProps = (dispatch, ownProps) => ({
onClick: () => dispatch(setVisibilityFilter(ownProps.filter))
})
export default connect(
mapStateToProps,
mapDispatchToProps
)(Link)
我的理解:mapStateToProps的第二个参数是ownProps,这个参数的值为传入到组件的props。只要组件接受到新的props,mapStateToProps也会被调用。
最外层
import React from 'react'
import FilterLink from '../containers/FilterLink'
import { VisibilityFilters } from '../actions'
const Footer = () => (
Show:
All
Active
Completed
)
export default Footer
filter属性作为FilterLink 的实参,通过connect 传入到子组件Link ,Link可获取得到其chirdren值
ps:写的有点乱,不明白可以留言。