使用react-redux 记录

1,332 阅读2分钟

useSelector

import { useSelector } from "react-redux";

const account: IAccount = useSelector((state: IStateType) => state.account);
import {Provider} from "react-redux";
import store from "./store/store";

ReactDOM.render(<Provider store={store}><App /></Provider>, 
document.getElementById('root'));

推荐使用 @reduxjs/toolkit 代替 createStore

store.ts

import { createStore, applyMiddleware, Store  } from "redux";
import thunkMiddleware from "redux-thunk";
import rootReducers from "./reducers/root.reducer";

const store: Store = createStore(rootReducers, applyMiddleware(
    thunkMiddleware
));

store.subscribe(() => {});
export default store;

@reduxjs/toolkit

zhuanlan.zhihu.com/p/382487951

import { configureStore } from '@reduxjs/toolkit';
import counterSlice from './slice/counterSlice';

export default configureStore({
    reducer: {
        counter: counterSlice,
    }
})

createSlice

import { createSlice } from "@reduxjs/toolkit";

export const counterSlice = createSlice({
  name: "counter", // 命名空间,在调用action的时候会默认的设置为action的前缀
  // 初始值
  initialState: {
    count: 1,
    title: "redux toolkit pre",
  },
  // 这里的属性会自动的导出为actions,在组件中可以直接通过dispatch进行触发
  reducers: {
    increment(state, { payload }) {
      // console.log(action);
      state.count = state.count + payload.step; // 内置了immutable
    },
    decrement(state) {
      state.count -= 1;
    },
  },
});

// 导出actions
export const { increment, decrement } = counterSlice.actions;

// 内置了thunk插件,可以直接处理异步请求
export const asyncIncrement = (payload) => (dispatch) => {
  setTimeout(() => {
    dispatch(increment(payload));
  }, 2000);
};

export default counterSlice.reducer; // 导出reducer,在创建store时使用到

• 在项目中使用

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import './index.css';
import App from './App';
import store from './store';

ReactDOM.render(
 <Provider store={store}>
 <App />
 </Provider>,
 document.getElementById('root')
);
在组件内部,使用useState和useDispatch可以直接获取state数据与dispatch方法
import { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { increment, asyncIncrement } from './store/features/counterSlice'; // 引入actions

function App() {
 const { count } = useSelector((state) => state.counter);
 const dispatch = useDispatch();
 return (
 <div className='App'>
 <button
 onClick={() => {
 dispatch(increment({ step: 2 })); // dispatch派发action
        }}
 >
        {count}
 </button>
 <hr />
 <button
 onClick={() => {
 dispatch(asyncIncrement({ step: 1 }));
        }}
 >
        {count}
 </button>
 </div>
  );
}

export default App;

创建异步action

import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
// createAsyncThunk创建一个异步的action,这个方法被触发的时候会有三个状态
// pending(进行中) fulfilled(成功) rejected(失败)

import { increment } from './counterSlice';

// 发起网络请求获取数据
const loadMoviesAPI = () =>
 fetch(
 'https://pcw-api.iqiyi.com/search/recommend/list?channel_id=1&data_type=1&mode=11&page_id=2&ret_num=48'
  ).then((res) => res.json());

// 这个action是可以直接调用的,用来处理异步操作获取数据
export const loadData = createAsyncThunk('movie/loadData', async () => {
 const res = await loadMoviesAPI();
 return res; // 此处的返回结果会在 .fulfilled中作为payload的值
});

export const movieSLice = createSlice({
 name: 'movie',
 initialState: {
 list: [],
 totals: 0,
  },
 reducers: {
 loadDataEnd(state, { payload }) {
 state.list = payload;
 state.totals = payload.length;
    },
  },
 // 可以额外的触发其他slice中的数据关联改变
 extraReducers: {
    [loadData.fulfilled](state, { payload }) {
 console.log(payload);
 state.list = payload.data.list;
    },
    [loadData.rejected](state, err) {
 console.log(err);
    },
    [loadData.pending](state) {
 console.log('进行中');
    },
  },
});

export const { loadDataEnd } = movieSLice.actions;
export default movieSLice.reducer;