我理解的todos(redux+react-redux)

demo地址:

git clone https://github.com/reactjs/redux.git
cd redux/examples/todos
npm install
npm start

3.第一部分(如图)

我理解的todos(redux+react-redux)_第1张图片
addTodo.png
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 (
        
{ e.preventDefault() //阻止默认事件,比如这里点击按钮会刷新页面 dispatch(addTodo(input.value)) input.value = '' } }> { input = node }} />
) } 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绑定到组件上

第二部分(如图)

我理解的todos(redux+react-redux)_第2张图片
todoList.png
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}

    第三部分(如图)

    我理解的todos(redux+react-redux)_第3张图片
    footer.png
    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:写的有点乱,不明白可以留言。

    你可能感兴趣的:(我理解的todos(redux+react-redux))