所以我创建了一个react redux工具包应用程序,并尝试使用redux和操作。
我有一个简单的反应组件,看起来像这样:
import React, { useState } from 'react';
import { useAppSelector, useAppDispatch } from '../../app/hooks';
import {
setBoard,
fetchBoardAsync,
selectBoard
} from './boardSlice';
import styles from './Board.module.css';
export function Board() {
const board = useAppSelector(selectBoard);
const dispatch = useAppDispatch();
console.log(JSON.stringify(board));
return (
<div>
<div className={styles.row}>
<h3>Board</h3>
<button
className={styles.asyncButton}
onClick={() => dispatch(fetchBoardAsync(""))}
>
Fetch board Data from API
</button>
</div>
</div>
);
}
当我点击按钮时,它会获取一些JSON,但现在它只是硬编码的JSON变量。
// A mock function to mimic making an async request for data
export function fetchBoard() {
return new Promise<{ data: any }>((resolve) =>
setTimeout(() => resolve({ data: boardJson} ), 50)
);
}
boardJson就是:
let boardJson = { .... }
我的boardSlice看起来像:
import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit';
import { RootState, AppThunk } from '../../app/store';
import { fetchBoard } from './boardAPI';
export interface BoardState {
board: any;
status: 'idle' | 'loading' | 'failed';
}
const initialState: BoardState = {
board: {},
status: 'idle',
};
export const fetchBoardAsync = createAsyncThunk(
'board/fetchBoard',
async (boardId: string) => {
const response = await fetchBoard();
console.log('fetch board returned data...' + JSON.stringify(response.data));
return response.data;
}
);
export const boardSlice = createSlice({
name: 'board',
initialState,
// The `reducers` field lets us define reducers and generate associated actions
reducers: {
setBoard: (state, action: PayloadAction<any>) => {
state.board = action.payload;
}
},
我有两个问题。
#1
当我点击按钮,它取出电路板时,我如何将结果保存到我的redux状态?
#2此外,在我的Board组件中,如何在组件加载时运行fetchBoard,而不必单击按钮来触发它?(我认为这曾经是一个类似componentDidMount的组件生命周期事件(
当我点击按钮并取出板时,我如何将结果保存到我的redux状态?
您的boardSlice
减速器几乎达到了预期效果。在reducers字段中,您提供了一个关键字/reducer值的对象。Redux无法将密钥setBoard
与fetchBoardAsync
创建的操作相关联。如果你是dispatch({ type: 'setBoard', payload })
,那么你会看到你的减速器像预期的那样着火。请注意该类型与异径键是如何相同的。
Redux文档中的createAsyncThunk
示例
RTK 中的匹配实用程序
相反,您可以使用RTK生成器语法和匹配器来获得所需结果:
export const boardSlice = createSlice({
name: 'board',
initialState,
extraReducers(builder) {
builder.addCase(fetchBoardAsync.fulfilled, (state, action) => {
state.board = action.payload;
})
},
};
#2此外,在我的Board组件中,当组件加载时,我如何运行fetchBoard,而不必单击按钮来触发它?(我认为这曾经是一个类似componentDidMount的组件生命周期事件(
在功能组件中,大多数React开发人员使用React钩子useEffect
来管理副作用,其方式与componentDidMount
/componentWillMount
和componentWillUnmount
类似。文档对开发人员利用这个钩子的所有方式提供了很多清晰的信息。
例如:
import React, { useEffect, useState } from 'react';
import { useAppSelector, useAppDispatch } from '../../app/hooks';
import {
setBoard,
fetchBoardAsync,
selectBoard
} from './boardSlice';
import styles from './Board.module.css';
export function Board() {
const board = useAppSelector(selectBoard);
const dispatch = useAppDispatch();
useEffect(() => {
dispatch(fetchBoardAsync(""))
}, []); // an empty dependency array tells React to only run the effect after mount
console.log(JSON.stringify(board)); // may not have loaded yet
return (
<div>
{/* snip */}
</div>
);
}
一旦被调度,thunks就会接收到用于额外Redux功能的第二个参数。传统的thunk是调度函数的结果,它接收带有以下签名的redux API:
function fetchBoardAsync() {
return (dispatch, getState) => {
// now you can dispatch even more actions!
// I don't believe this is necessary for your current use-case, but this is helpful for complicated side-effects in many apps
}
}
Redux thunk文档
使用createAsyncThunk
时,签名如下:
function fetchBoardAsync(arg, api) {
const { dispatch, extra, fulfillWithValue, getState, rejectWithValue, requestId, signal } = api;
}
createAsyncThunk签名
记住,在thunk回调内部使用dispatch之前,您仍然必须调度thunk(函数或createAsyncThunk
的返回值(本身。