坚持周总结系列第六周(2020.5.24)

React全家桶

Redux

  • 创建store
import { createStore } from 'redux'

const counterReducer = (state = 0, action) => {
  switch (action.type) {
    case 'add':
      return state + 1
    case 'minus':
      return state - 1
    default:
      return state
  }
}

const store = createStore(counterReducer)

export default store
  • 创建ReduxTest
import React, { Component } from 'react'
import store from '../store'

export default class ReduxTest extends Component {
  render () {
    return (
      <div>
        <p>{store.getState()}</p>
        <div>
          <button onClick={() => store.dispatch({ type: 'add' })}>+</button>
          <button onClick={() => store.dispatch({ type: 'minus' })}>-</button>
        </div>
      </div>
    )
  }
}
  • 订阅状态变更
import store from './store'

const render = () => {
  ReactDOM.render(<App />, document.querySelector('#root'))
}

render()

store.subscribe(render)
  • 使用react-redux
import { Provider } from 'react-redux'

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.querySelector('#root')
)
  • 获取数据状态
import React, { Component } from 'react'
import { connect } from 'react-redux'

@connect(state => ({ num: state }), {
  add: () => ({ type: 'add' }),
  minus: () => ({ type: 'minus' })
})
class ReduxTest extends Component {
  render() {
    return (
      <div>
        <p>{this.props.num}</p>
        <div>
          <button onClick={this.props.add}>+</button>
          <button onClick={this.props.minus}>-</button>
        </div>
      </div>
    )
  }
}

export default ReduxTest
  • 应用中间件
import { createStore, applyMiddleware } from 'redux'
import logger from 'redux-logger'
import thunk from 'redux-thunk'

const counterReducer = (state = 0, action) => {
  switch (action.type) {
    case 'add':
      return state + 1
    case 'minus':
      return state - 1
    default:
      return state
  }
}

const store = createStore(counterReducer, applyMiddleware(logger, thunk))

export default store
  • 使用异步操作数据
@connect(state => ({ num: state }), {
  ...
  asyncAdd: () => dispatch => {
    setTimeout(() => {
      dispatch({ type: 'add' })
    }, 1000)
  }
})
  • 代码优化
// reducer.js
const counterReducer = (state = 0, action) => {
  switch (action.type) {
    case 'add':
      return state + 1
    case 'minus':
      return state - 1
    default:
      return state
  }
}

export default counterReducer
// action.js
export const add = num => ({ type: 'add', payload: num })
export const minus = num => ({ type: 'minus', payload: num })
export const asyncAdd = num => dispatch => {
  setTimeout(() => {
    dispatch({ type: 'add', payload: num })
  }, 1000)
}
// store/index.js
import { createStore, applyMiddleware } from 'redux'
import logger from 'redux-logger'
import thunk from 'redux-thunk'
import reducer from './reducer'

const store = createStore(reducer, applyMiddleware(logger, thunk))

export default store
// ReduxTest.tsx
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { add, minus, asyncAdd } from '../store/action'

@connect(state => ({ num: state }), { add, minus, asyncAdd })
class ReduxTest extends Component {
  render() {
    return (
      <div>
        <p>{this.props.num}</p>
        <div>
          <button onClick={this.props.add}>+</button>
          <button onClick={this.props.asyncAdd}>++</button>
          <button onClick={this.props.minus}>-</button>
        </div>
      </div>
    )
  }
}

export default ReduxTest
  • 模块化
// store/index.js
import { createStore, applyMiddleware, combineReducers } from 'redux'
import { composeWithDevTools } from 'redux-devtools-extension'
import logger from 'redux-logger'
import thunk from 'redux-thunk'
import reducer from './reducer'

const store = createStore(
  combineReducers({
    counter: reducer
  }),
  composeWithDevTools(applyMiddleware(logger, thunk))
)

export default store
// store/reducer.js
let defaultState = { count: 0 }

const counterReducer = (state = defaultState, action) => {
  switch (action.type) {
    case 'add':
      return { count: state.count + 1 }
    case 'minus':
      return { count: state.count - 1 }
    default:
      return state
  }
}

export default counterReducer
// store/action.js
export const add = num => ({ type: 'add', payload: num })
export const minus = num => ({ type: 'minus', payload: num })
export const asyncAdd = num => dispatch => {
  setTimeout(() => {
    dispatch({ type: 'add', payload: num })
  }, 1000)
}
// 在组件中使用
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { add, minus, asyncAdd } from '../store/action'

class ReduxTest extends Component {
  render () {
    return (
      <div>
        <p>{this.props.num}</p>
        <div>
          <button onClick={this.props.add}>+</button>
          <button onClick={this.props.asyncAdd}>++</button>
          <button onClick={this.props.minus}>-</button>
        </div>
      </div>
    )
  }
}

const mapStateToProps = state => ({
  num: state.counter.count
})
const mapDispatchToProps = {
  add,
  minus,
  asyncAdd
}

export default connect(mapStateToProps, mapDispatchToProps)(ReduxTest)

Router

  • 总路由
import React from 'react'
import { BrowserRouter, Link, Route } from 'react-router-dom'
import FruitList from './FruitList'
import FruitAdd from './FruitAdd'
import Login from './Login'
import PrivateRoute from './PrivateRoute'

function Container () {
  return (
    <BrowserRouter>
      <nav>
        <Link to='/list'>水果列表</Link>
        <Link to='/add'>添加水果</Link>
      </nav>
      <Route path='/' component={() => <div>首页</div>} />
      <PrivateRoute path='/list' component={FruitList} />
      <Route path='/add' component={FruitAdd} />
      <Route path='/login' component={Login} />
    </BrowserRouter>
  )
}

export default Container
  • 路由嵌套、路由传参
import React from 'react'
import Detail from './Detail'
import { connect } from 'react-redux'
import { Link, Route } from 'react-router-dom'

function FruitList ({ fruits }) {
  return (
    <div>
      <ul>
        {fruits.map(f => (
          <li key={f}>
            <Link to={`/list/detail/${f}`}>{f}</Link>
          </li>
        ))}
      </ul>
      <Route path='/list/detail/:fruit' component={Detail} />
    </div>
  )
}

const mapStateToProps = state => ({
  fruits: state.fruit.fruits
})

export default connect(mapStateToProps)(FruitList)
  • 接收路由参数
import React from 'react'

function Detail ({ match, history, location }) {
  return (
    <div>
      <h1>{match.params.fruit}</h1>
      <button onClick={history.goBack}>返回</button>
    </div>
  )
}

export default Detail
  • 路由守卫
import React from 'react'
import { Route, Redirect } from 'react-router-dom'
import { connect } from 'react-redux'

function PrivateRoute ({ component: Component, isLogin, ...rest }) {
  return (
    <Route
      {...rest}
      render={props =>
        isLogin ? (
          <Component {...props} />
        ) : (
          <Redirect
            to={{
              pathname: '/login',
              state: { redirect: props.location.pathname }
            }}
          />
        )
      }
    />
  )
}

const mapStateToProps = state => ({
  isLogin: state.user.isLogin
})

export default connect(mapStateToProps)(PrivateRoute)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值