1)redux初体验(问题记录)

1.redux理解

是什么?: redux是专门做状态管理的独立第3方库, 不是react插件
作用?: 对应用中状态进行集中式的管理(写/读)
开发: 与react-redux, redux-thunk等插件配合使用

2. redux相关API

redux中包含: createStore(), applyMiddleware(), combineReducers()
store对象: getState(), dispatch(), subscribe()
react-redux: <Provider>, connect()()

3. redux核心概念(3个)

action: 
    默认是对象(同步action), {type: 'xxx', data: value}, 需要通过对应的actionCreator产生, 
    它的值也可以是函数(异步action), 需要引入redux-thunk才可以
reducer
    根据老的state和指定的action, 返回一个新的state
    不能修改老的state
store
    redux最核心的管理对象
    内部管理着: state和reducer
    提供方法: getState(), dispatch(action), subscribe(listener)

4. redux工作流程

 redux使用记录

 目标效果:

目录结构:创建redux文件夹便于模块化管理

 

// action-types.js 存储常量名

// action 对象的 type 常量名称模块
export const INCREMENT ='increment'
export const DECREMENT ='decrement'
// reducer.js内(定义方法改变redux内state的值)
import { INCREMENT, DECREMENT } from "./action-types";

export function counter (state = 0, action) {
  switch (action.type) {
    case INCREMENT:
      return state += action.data
    case DECREMENT:
      return state -= action.data
    default:
      return state
  }
}
// index.js内
import React from "react";
import { createRoot } from 'react-dom/client';
import { configureStore } from '@reduxjs/toolkit'

import { counter } from './redux/reducers'
import App from "./components/app";
// 根据counter函数创建store对象
const store = configureStore({ reducer: counter })
console.log(store, 'store');


const root = createRoot(document.getElementById('root'));

function render () {
  root.render(
    // 将store传给app让其与组件有关联
    <App store={store} />
  );
}
render()
// 监听store内容更新dom 
store.subscribe(() => {
  render()
})
// app.jsx内
// 导入 React 模块
import React, { Component } from "react";
// 引入常量名称
import { INCREMENT, DECREMENT } from "../redux/action-types";
// 引入action内的所有方法

// 暴露并创建react类
export default class App extends Component {
  addCountFn = () => {
    // store.dispatch调用store内的action函数
    this.props.store.dispatch({ type: INCREMENT, data: this.select.value * 1 });
  };
  delCountFn = () => {
    this.props.store.dispatch({ type: DECREMENT, data: this.select.value * 1 });
  };
  incrementOddFn = () => {
    const count = this.props.store.getState();
    if (count % 2 === 1) {
      this.props.store.dispatch({
        type: INCREMENT,
        data: this.select.value * 1,
      });
    }
  };
  incrementAsyncFn = () => {
    setTimeout(() => {
      this.props.store.dispatch({
        type: INCREMENT,
        data: this.select.value * 1,
      });
    }, 1000);
  };
  render() {
    const count = this.props.store.getState();
    return (
      <div>
        <h2>click {count} times</h2>
        <select ref={(select) => (this.select = select)}>
          <option value="1">1</option>
          <option value="2">2</option>
          <option value="3">3</option>
        </select>
        &nbsp;
        <button onClick={this.addCountFn}>+</button>&nbsp;
        <button onClick={this.delCountFn}>-</button>&nbsp;
        <button onClick={this.incrementOddFn}>increment if odd</button>&nbsp;
        <button onClick={this.incrementAsyncFn}>increment async</button>
      </div>
    );
  }
}

优化 (模块化store)

之后的编码结构 只要用到redux 就先创建这四个文件夹

actions-type.js、reducers.js内代码不变

// actions.js内
import { INCREMENT,DECREMENT } from "./action-types";
export const increment = (number) => ({ type: INCREMENT, data: number })
export const decrement = (number) => ({ type: DECREMENT, data: number })
// store.js内
import { configureStore } from '@reduxjs/toolkit'

import { counter } from './reducers'

// 根据counter函数创建store对象
const store = configureStore({ reducer: counter })
console.log(store, 'store');
export default store
// app.jsx
import React, { Component } from "react";
// 引入常量名称
// import { INCREMENT, DECREMENT } from "../redux/action-types";
// 引入action内的所有方法
import * as actions from "../redux/actions";
// 暴露并创建react类
export default class App extends Component {
  addCountFn = () => {
    // store.dispatch调用store内的action函数
    this.props.store.dispatch(actions.increment(this.select.value * 1));
  };
  delCountFn = () => {
    this.props.store.dispatch(actions.decrement(this.select.value * 1));
  };
  incrementOddFn = () => {
    const count = this.props.store.getState();
    if (count % 2 === 1) {
      this.props.store.dispatch(actions.increment(this.select.value * 1));
    }
  };
  incrementAsyncFn = () => {
    setTimeout(() => {
      this.props.store.dispatch(actions.increment(this.select.value * 1));
    }, 1000);
  };
  render() {
    const count = this.props.store.getState();
    return (
      <div>
        <h2>click {count} times</h2>
        <select ref={(select) => (this.select = select)}>
          <option value="1">1</option>
          <option value="2">2</option>
          <option value="3">3</option>
        </select>
        &nbsp;
        <button onClick={this.addCountFn}>+</button>&nbsp;
        <button onClick={this.delCountFn}>-</button>&nbsp;
        <button onClick={this.incrementOddFn}>increment if odd</button>&nbsp;
        <button onClick={this.incrementAsyncFn}>increment async</button>
      </div>
    );
  }
}
// index.js
import React from "react";
import { createRoot } from 'react-dom/client';

import App from "./components/app";
import store from './redux/store'

const root = createRoot(document.getElementById('root'));

function render () {
  root.render(
    <App store={store} />
  );
}
render()
// 监听store内容更新dom 
store.subscribe(() => {
  render()
})

遇到的问题

问题一:

// index.js内
...引入的就不复制了

function render () {
  createRoot(document.getElementById('root')).render(
    <App store={store} />
  );
}
render()
// 监听store内容更新dom 
store.subscribe(() => {
  render()
})

报错:Warning: You are calling ReactDOMClient.createRoot() on a container that has already been passed to createRoot() before. Instead, call root.render() on the existing root instead if you want to update it.

修改:

// index.js内
const root = createRoot(document.getElementById('root'));

function render () {
  root.render(
    <App store={store} />
  );
}
render()
// 监听store内容更新dom 
store.subscribe(() => {
  render()
})

问题二:引入 createStore被划掉问题

// index.js内
// 官方推荐 下载@reduxjs/toolkit这个包 用configureStore替换createStore
import { configureStore } from '@reduxjs/toolkit'

import rootReducer from './reducers'

const store = configureStore({ reducer: rootReducer })

官网地址: configureStore | Redux Toolkit

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值