redux react-redux简介

  • 相对于vue的vuex而言 react的redux确实要复杂许多,并且没有相对完善适合初学者的文档,所以学习起来特别困难,这里用一个小例子来写一下 redux react-redux的简单用法,事先声明所有的文件地址请读者根据自己的文件地址写连接
    首先是安装
// 个人比较喜欢用yarn 不喜欢的可以自行换成npm 或者 cnpm
	yarn add redux --save
	yarn add react-redux --save
  • 在项目中创建store文件夹 并在其中创建actions.js 和 reducer.js
	//redux定义修改state数据的唯一方法就是通过dispatch方法触发action
	// 我们来定义一些待触发的action
	let nextTodoId = 0
	const addTodo = text => {
	  // console.log(text)
	  return {
	    type: 'ADD_TODO',
	    id: nextTodoId++,
	    text
	  }
	}
	
	const setVisibilityFilter = filter => {
	  return {
	    type: 'SET_VISIBILITY_FILTER',
	    filter
	  }
	}
	
	const toggleTodo = id => {
	  return {
	    type: 'TOGGLE_TODO',
	    id
	  }
	}
	
	export {
	    addTodo,
	    setVisibilityFilter,
	    toggleTodo
	}

接下来编写reducer

	// reducer可以编写自己想存储的数据及方法 因为数据或者方法可能会有很多 所以可以使用
	// combineReducers 方法将数据和方法合并在一起方便将来创建存储库
	
	import { combineReducers } from 'redux'
	// 生成要保存的todos数据 这里因为任务是集合 所以返回的是数组
	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
	    }
	}
	// 这里多写一个方法 提供给合并演示用 这里并未使用该方法 只为了方便读者理解combineReducers的作用
	const visibilityFilter = (state = 'SHOW_ALL', action) => {
	    switch (action.type) {
	        case 'SET_VISIBILITY_FILTER':
	        return action.filter
	        default:
	        return state
	    }
	}
	
	const todoApp = combineReducers({
	    todos,
	    visibilityFilter
	})
	
	export default todoApp

写好reducer就可以创建自己的仓库了

  • 在 store文件夹下创建一个index.js文件, 代码如下
import React from 'react';
// 从redux导入创建仓库的方法
import { createStore } from 'redux';
// 导入编写完成的reducer
import todo from './reducer'

const store = createStore(todo)

export default store

warn这里引用文档中的一句话技术上讲,容器组件就是使用 store.subscribe() 从 Redux state 树中读取部分数据,并通过 props 来把这些数据提供给要渲染的组件。你可以手工来开发容器组件,但建议使用 React Redux 库的 connect() 方法来生成,这个方法做了性能优化来避免很多不必要的重复渲染。(这样你就不必为了性能而手动实现 React 性能优化建议 中的 shouldComponentUpdate 方法。)

使用 connect() 前,需要先定义 mapStateToProps 这个函数来指定如何把当前 Redux store state 映射到展示组件的 props 中。例如,VisibleTodoList 需要计算传到 TodoList 中的 todos,所以定义了根据 state.visibilityFilter 来过滤 state.todos 的方法,并在 mapStateToProps 中使用。
其实就是说我们可以通过connect来写传入自己想要传递给组件的数据 而不是每次都用整个仓库这样并不友好
方法的就比如下面这种

	import { connect } from 'react-redux'
	import { toggleTodo } from '../../store/actions'
	import Tasks from '../tasks/Tasks'
	
	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 => {
	  // console.log(state) // 所有的reducer方法
	  return {
	    todos: getVisibleTodos(state.todos, state.visibilityFilter)
	  }
	}
	
	const mapDispatchToProps = dispatch => {
	  return {
	    onTodoClick: id => {
	      dispatch(toggleTodo(id))
	    }
	  }
	}
	// connect的参数将作为数据传递给tasks组件
	// 这里表示的是将todos和onToDoClick传入tasks组件的props中
	const VisibleTodoList = connect(
	  mapStateToProps, 
	  mapDispatchToProps
	)(Tasks)
	
	export default VisibleTodoList
  • 至此我们的redux仓库就创建完成了 接下来就是使用了
    在项目的入口文件index.js中
	import React from 'react';
	import ReactDOM from 'react-dom';
	import './index.css';
	import App from './App';
	// provider可以魔法性的让所有的组件都访问到store
	import { Provider } from 'react-redux'
	// 导入定义好的store
	import store from './store/index'
	ReactDOM.render(
	  <Provider store={store}>
	    <App />
	  </Provider>,
	  document.getElementById('root')
	);

准备工作完毕 接下来就是组件了

//首先是App.js
import React from 'react'
import Header from './components/header/Header'
import Tasks from './components/tasks/Tasks'
import Visiable from './components/visiable/visiable'
class App extends React.Component {
  render() {
    return (
      <div className="App">
        <Header />
        <Visiable />
      </div>
    );
  }
}

export default App;
//这个是header组件
import React from 'react'
import './Header.css'
import { connect } from 'react-redux'
import { addTodo } from '../../store/actions'
class Header extends React.Component {
    constructor(props) {
        super()
    }
    add = (e) => {
        if(e.keyCode === 13) {
            this.props.dispatch(addTodo(e.target.value))
        }
    }
    render() {
        return (
            <div className="header_box">
                <div><span className="title">ToDoList</span><input placeholder="添加todo" onKeyUp={this.add}/></div>
            </div>
        )
    }
}
Header = connect()(Header)
export default Header
···
```javascript
	//这里是任务组件
	import React,{Component} from 'react';
	import './Task.css';
	import { PropTypes } from 'prop-types'; // 定义接收的值的类型
	
	class Tasks extends Component {
	    render() { 
	        return (  
	            <div className="task_list">
	                <h3>{this.props.title}</h3>
	                <ul>
	                    {this.props.todos.map(todo => {
	                        return <li 
	                        className="item_task" 
	                        key={todo.id} 
	                        onClick={() => this.props.onTodoClick(todo.id)}
	                        style={
	                            {
	                                textDecoration: todo.completed ? 'line-through' : 'none'
	                            }
	                        }
	                        >
	                            <div>
	                                <input type="checkbox" />
	                                <div>{todo.text}</div>
	                            </div>
	                            <span className="del">-</span>
	                        </li>
	                    })}
	                </ul>
	            </div>
	        );
	    }
	}
	Tasks.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 Tasks;
  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值