redux使用

redux使用

环境准备

需要安装以下

yarn add @reduxjs/toolkit react-redux
# or
npm i -D @reduxjs/toolkit react-redux

仓库创建

主仓库

创建src/store/features

创建index.tssrc/store目录下

// 创建仓库
import { configureStore } from '@reduxjs/toolkit';

/**
 * 子仓库
 * features:也可以命名为 module
 */
import counter from '@/store/features/counter';
import home from '@/store/features/home';

/** 初始化仓库 */
const store = configureStore({
  reducer: { counter, home },
});

// 当初仓库
export default store;

子仓库

如果需要编写异步函数,需要使用createAsyncThunk创建

  • extraReducers下有三种状态
    1. pending:正在发送
    2. fulfilled:获取成功
    3. rejected:失败

第一种写法

这种写法是为了往后兼容

home.ts

位于src/store/features

import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import { getBanners } from '@/api/home';

/** 获取导航栏 */
export const fetchHomeMultidataAction = createAsyncThunk('fetch/homeBannersData', async () => {
  const result = await getBanners();
  return result.data;
});

const homeSlice = createSlice({
  name: 'home',
  initialState: {
    banners: [],
    recommends: [],
  },
  reducers: {
    /** 获取板块 */
    changeBanners(state, { payload }) {
      state.banners = payload;
    },

    /** 获取评论 */
    changeRecommends(state, { payload }) {
      state.recommends = payload;
    },
  },

  extraReducers: (builder: any) => {
    /** 正在发送 */
    builder.addCase(fetchHomeMultidataAction.pending, (state: any, { payload }: any) => {
      console.log('处理正在进行中的逻辑');
    });
    /** 请求成功 */
    builder.addCase(fetchHomeMultidataAction.fulfilled, (state: any, { payload }: any) => {
      console.log('处理成功的结果,并将结果赋值');
      state.banners = payload;
    });
    /** 请求失败 */
    builder.addCase(fetchHomeMultidataAction.rejected, (state: any, { payload }: any) => {
      console.log('处理失败的结果');
    });
  },
});

export const { changeBanners, changeRecommends } = homeSlice.actions;
export default homeSlice.reducer;

第二种写法

需要注意的是,这种写法将在v2版本中移出

home.ts

import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import { getBanners } from '@/api/home';

/** 获取导航栏 */
export const fetchHomeMultidataAction = createAsyncThunk('fetch/homeBannersData', async () => {
  const result = await getBanners();
  return result.data;
});

const homeSlice = createSlice({
  name: 'home',
  initialState: {
    banners: [],
    recommends: [],
  },
  // 普通修改
  reducers: {
    /** 获取板块 */
    changeBanners(state, action) {
      // 未解构出来的是action,里面有 payload
      state.banners = action.payload;
    },

    /** 获取评论 */
    changeRecommends(state, { payload }) {
      state.recommends = payload;
    },
  },
  // 异步修改 -- 这种写法将被弃用
  extraReducers: {
    /** 正在发送 */
    [fetchHomeMultidataAction.pending.toString()](state: any, action: any) {
      console.log('处理正在进行中的逻辑');
    },
    /** 完成 */
    [fetchHomeMultidataAction.fulfilled.toString()](state: any, { payload }) {
      console.log('处理成功的结果,并将结果赋值');
      state.banners = payload;
    },
    /** 失败 */
    [fetchHomeMultidataAction.rejected.toString()](state: any, action: any) {
      console.log('处理失败的结果');
    },
  },
});

export const { changeBanners, changeRecommends } = homeSlice.actions;
export default homeSlice.reducer;

组件使用

类组件

import { connect } from 'react-redux';
import { Component } from 'react';
import { addNumber, subNumber } from '@/store/features/counter';
import { fetchHomeMultidataAction } from '@/store/features/home';

interface Props {
  counter: number;
  subNumber: Function;
  addNumber: Function;
  fetchHomeMultidataAction: Function;
  banners: [];
  recommends: [];
}

export class Profile extends Component<Props> {
  /** 当组件刚挂载时,派发请求 */
  componentDidMount() {
    this.props.fetchHomeMultidataAction();
  }

  render() {
    const { counter, banners, recommends } = this.props;

    return (
      <div>
        <div>
          <h3>Profile counter {counter}</h3>
          <button onClick={() => this.props.addNumber(6)}>+6</button>
          <button onClick={() => this.props.subNumber(6)}>-6</button>
        </div>
        <ul>
          {banners.map((item: any) => {
            return <li key={item.boardId}>{item.boardName}</li>;
          })}
        </ul>

        <ul>
          {recommends.map(item => (
            <li>{item}</li>
          ))}
        </ul>
      </div>
    );
  }
}

/** 用于赋值, */
const mapStateToProps = (state: any) => ({
  counter: state.counter.counter,
  banners: state.home.banners,
  recommends: state.home.recommends,
});

// 用于派发请求,由于本身有 dispatch 所以不用使用 store.dispatch
const mapDispatchToProps = (dispatch: any) => ({
  addNumber(num: number) {
    dispatch(addNumber(num));
  },
  subNumber(num: number) {
    dispatch(subNumber(num));
  },
  /** 这个是异步请求 */
  fetchHomeMultidataAction() {
    dispatch(fetchHomeMultidataAction());
  },
});

// 用于连接组件和仓库进行
export default connect(mapStateToProps, mapDispatchToProps)(Profile);

函数组件

函数组件和类组件同理

import { useEffect } from 'react';
import { connect } from 'react-redux';
import { addNumber, subNumber } from '@/store/features/counter';
import { fetchHomeMultidataAction } from '@/store/features/home';

interface Props {
  counter: number;
  subNumber: Function;
  addNumber: Function;
  fetchHomeMultidata: Function;
  banners: [];
  recommends: [];
}

export function About(props: Props) {
  const { counter, banners, recommends } = props;

  useEffect(() => {
    props.fetchHomeMultidata('about');
  }, [counter]);

  return (
    <div>
      <h1>About</h1>
      <div>
        <h3>About中的按钮---要求的数字{counter}</h3>
        <button onClick={() => props.addNumber(6)}>+6</button>
        <button onClick={() => props.subNumber(6)}>-6</button>
      </div>
      {/* 渲染 */}
      <ul>
        {banners.map((item: any) => (
          <li key={item.boardId}>{item.cover}</li>
        ))}
      </ul>
      {/* 渲染 */}
      <ul>
        {recommends.map((item: any) => (
          <li key={item.boardId}>About中boardId={item.boardId}</li>
        ))}
      </ul>
    </div>
  );
}

/** 用于赋值 */
const mapStateToProps = (state: any) => ({
  counter: state.counter.counter,
  banners: state.home.banners,
  recommends: state.home.recommends,
});

const mapDispatchToProps = (dispatch: any) => ({
  addNumber(num: number) {
    dispatch(addNumber(num));
  },
  subNumber(num: number) {
    dispatch(subNumber(num));
  },
  fetchHomeMultidata(str: string) {
    dispatch(fetchHomeMultidataAction(str));
  },
});

// 用于派发请求
export default connect(mapStateToProps, mapDispatchToProps)(About);

你可能感兴趣的:(react学习,javascript,前端,react)