如何使用Redux工具包&x27;什么是createSlice?
======================TLDR========================== @markerikson(见接受的答案)善意地指出了当前的解决方案和未来的解决方案 编辑:2020年11月15日: RTK确实支持使用thunk中间件的Reducer中的thunk(参见答案) 在1.3.0版本(目前alpha于2020年2月发布)中,有一个助手方法如何使用Redux工具包&x27;什么是createSlice?,redux,redux-thunk,redux-toolkit,Redux,Redux Thunk,Redux Toolkit,======================TLDR========================== @markerikson(见接受的答案)善意地指出了当前的解决方案和未来的解决方案 编辑:2020年11月15日: RTK确实支持使用thunk中间件的Reducer中的thunk(参见答案) 在1.3.0版本(目前alpha于2020年2月发布)中,有一个助手方法createAsyncThunk(),它将提供一些有用的功能(即触发3个“扩展”还原器,具体取决于承诺的状态) =======
createAsyncThunk()
,它将提供一些有用的功能(即触发3个“扩展”还原器,具体取决于承诺的状态)
========================================原2020年2月后==========================
我对Redux很陌生,遇到过Redux工具包(RTK),希望实现它提供的进一步功能(或者在这种情况下可能没有?)(2020年2月)
我的应用程序将调度到通过createSlice({})
创建的还原程序切片(请参阅)
到目前为止,这项工作非常出色。我可以轻松地使用内置的分派(操作)
和使用选择器(选择器)
分派操作,并很好地接收/响应组件中的状态更改
我想使用axios的异步调用从API获取数据,并在请求A)启动B)完成时更新存储
我看到过redux thunk,它似乎完全是为了这个目的而设计的……但是新的RTK似乎不支持在谷歌搜索之后的createSlice()
中使用它
以上是使用切片实现thunk的当前状态吗
我在文档中看到,您可以向切片中添加外部还原程序,但不确定这是否意味着我可以创建更多使用thunk的传统还原程序,并让切片实现它们
总的来说,RTK文档显示您可以使用thunk,这是一个误导,但似乎没有提到它不能通过新的slices api访问
来自
我的代码是一个片段,显示异步调用失败的地方,以及其他一些可以工作的示例还原程序
import { getAxiosInstance } from '../../conf/index';
export const slice = createSlice({
name: 'bundles',
initialState: {
bundles: [],
selectedBundle: null,
page: {
page: 0,
totalElements: 0,
size: 20,
totalPages: 0
},
myAsyncResponse: null
},
reducers: {
//Update the state with the new bundles and the Spring Page object.
recievedBundlesFromAPI: (state, bundles) => {
console.log('Getting bundles...');
const springPage = bundles.payload.pageable;
state.bundles = bundles.payload.content;
state.page = {
page: springPage.pageNumber,
size: springPage.pageSize,
totalElements: bundles.payload.totalElements,
totalPages: bundles.payload.totalPages
};
},
//The Bundle selected by the user.
setSelectedBundle: (state, bundle) => {
console.log(`Selected ${bundle} `);
state.selectedBundle = bundle;
},
//I WANT TO USE / DO AN ASYNC FUNCTION HERE...THIS FAILS.
myAsyncInSlice: (state) => {
getAxiosInstance()
.get('/')
.then((ok) => {
state.myAsyncResponse = ok.data;
})
.catch((err) => {
state.myAsyncResponse = 'ERROR';
});
}
}
});
export const selectBundles = (state) => state.bundles.bundles;
export const selectedBundle = (state) => state.bundles.selectBundle;
export const selectPage = (state) => state.bundles.page;
export const { recievedBundlesFromAPI, setSelectedBundle, myAsyncInSlice } = slice.actions;
export default slice.reducer;
我的商店设置(商店配置)
如有任何帮助或进一步指导,将不胜感激。使用
redux toolkit v1.3.0-alpha.8
试试这个
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
export const myAsyncInSlice = createAsyncThunk('bundles/myAsyncInSlice', () =>
getAxiosInstance()
.get('/')
.then(ok => ok.data)
.catch(err => err),
);
const usersSlice = createSlice({
name: 'bundles',
initialState: {
bundles: [],
selectedBundle: null,
page: {
page: 0,
totalElements: 0,
size: 20,
totalPages: 0,
},
myAsyncResponse: null,
myAsyncResponseError: null,
},
reducers: {
// add your non-async reducers here
},
extraReducers: {
// you can mutate state directly, since it is using immer behind the scenes
[myAsyncInSlice.fulfilled]: (state, action) => {
state.myAsyncResponse = action.payload;
},
[myAsyncInSlice.rejected]: (state, action) => {
state.myAsyncResponseError = action.payload;
},
},
});
我是Redux的维护者和Redux工具包的创建者 FWIW,没有关于使用Redux工具箱进行异步调用的内容 您仍然可以使用异步中间件(通常),获取数据,并根据结果分派操作 从Redux Toolkit 1.3开始,我们有一个名为的助手方法,它生成动作创建者,并为您请求生命周期动作调度,但它仍然是相同的标准过程 文档中的示例代码总结了使用情况
从'@reduxjs/toolkit'导入{createAsynchThunk,createSlice}
从“/userAPI”导入{userAPI}
//首先,创建thunk
const fetchUserById=createAsynchThunk(
“用户/fetchByIdStatus”,
异步(用户ID,thunkAPI)=>{
const response=await userAPI.fetchById(userId)
返回响应.data
}
)
//然后,在减速器中处理操作:
const usersSlice=createSlice({
名称:'用户',
initialState:{entities:[],正在加载:'idle'},
减速器:{
//标准减速器逻辑,每个减速器自动生成动作类型
},
外减速器:{
//在此处为其他操作类型添加还原器,并根据需要处理加载状态
[fetchUserById.Completed]:(状态、操作)=>{
//将用户添加到状态数组
state.entities.push(action.payload)
}
}
})
//稍后,根据需要在应用程序中发送thunk
分派(fetchUserById(123))
有关此主题的更多信息,请参阅
希望这能为你指明正确的方向 您可以使用
createAsyncThunk
创建thunk操作
,可以使用dispatch
teamSlice.ts
import {
createSlice,
createAsyncThunk,
} from "@reduxjs/toolkit";
const axios = require('axios');
export const fetchPlayerList = createAsyncThunk('team/playerListLoading',
(teamId:string) =>
axios
.get(`https://api.opendota.com/api/teams/${teamId}/players`)
.then(response => response.data)
.catch(error => error),
);
const teamInitialState = {
playerList: {
status: 'idle',
data: {},
error: {}
}
};
const teamSlice = createSlice({
name: 'user',
initialState: teamInitialState,
reducers: {},
extraReducers: {
[fetchPlayerList.pending.type]: (state, action) => {
state.playerList = {
status: 'loading',
data: {},
error: {}
};
},
[fetchPlayerList.fulfilled.type]: (state, action) => {
state.playerList = {
status: 'idle',
data: action.payload,
error: {}
};
},
[fetchPlayerList.rejected.type]: (state, action) => {
state.playerList = {
status: 'idle',
data: {},
error: action.payload,
};
},
}
});
export default teamSlice;
Team.tsx组件
import React from "react";
import { useSelector, useDispatch } from "react-redux";
import { fetchPlayerList } from './teamSlice';
const Team = (props) => {
const dispatch = useDispatch();
const playerList = useSelector((state: any) => state.team.playerList);
return (
<div>
<button
onClick={() => { dispatch(fetchPlayerList('1838315')); }}
>Fetch Team players</button>
<p>API status {playerList.status}</p>
<div>
{ (playerList.status !== 'loading' && playerList.data.length) &&
playerList.data.map((player) =>
<div style={{display: 'flex'}}>
<p>Name: {player.name}</p>
<p>Games Played: {player.games_played}</p>
</div>
)
}
</div>
</div>
)
}
export default Team;
从“React”导入React;
从“react-redux”导入{useSelector,useDispatch};
从“/teamSlice”导入{fetchPlayerList};
const团队=(道具)=>{
const dispatch=usedpatch();
constplayerlist=useSelector((state:any)=>state.team.playerList);
返回(
{dispatch(fetchPlayerList('1838315');}
>召集队员
API状态{playerList.status}
{(playerList.status!='loading'&&playerList.data.length)&&
playerList.data.map((player)=>
名称:{player.Name}
玩过的游戏:{玩家。玩过的游戏}
)
}
)
}
导出默认团队;
谢谢。我曾看到您对Git问题发表评论,但由于它仍然是开放的,我认为还没有实现(因此没有进一步冒险)。顺便说一句,工作做得很棒,等不及下一个主要版本了!我主要是一名Spring Boot后端开发人员,作为一名新手,整个前端世界让我头晕目眩,但您的工作使它非常易于理解和使用。也许我应该看看“高级”,但在做了几天的redux(和RTK的几个小时)之后,我并没有走那么远哈!太好了,谢谢你的积极反馈!是的,RTK文档目前是在假设您已经知道Redux是如何工作的情况下编写的,因此他们重点解释使用RTK与“手工”编写Redux逻辑的不同之处。在RTK1.3.0之后,我的下一个任务是添加一个新的Redux核心文档“快速入门”页面,该页面假设您是Redux新手,并展示了从零开始使用RTK编写Redux代码的最简单方法。这将是完美的。我发现自己潜入了前端的世界……在两周的时间里,我经历了以下的演变:1。仅对生命周期和状态进行反应。2.使用lifecycle、redux和MaterialUI。3.机智
import {
createSlice,
createAsyncThunk,
} from "@reduxjs/toolkit";
const axios = require('axios');
export const fetchPlayerList = createAsyncThunk('team/playerListLoading',
(teamId:string) =>
axios
.get(`https://api.opendota.com/api/teams/${teamId}/players`)
.then(response => response.data)
.catch(error => error),
);
const teamInitialState = {
playerList: {
status: 'idle',
data: {},
error: {}
}
};
const teamSlice = createSlice({
name: 'user',
initialState: teamInitialState,
reducers: {},
extraReducers: {
[fetchPlayerList.pending.type]: (state, action) => {
state.playerList = {
status: 'loading',
data: {},
error: {}
};
},
[fetchPlayerList.fulfilled.type]: (state, action) => {
state.playerList = {
status: 'idle',
data: action.payload,
error: {}
};
},
[fetchPlayerList.rejected.type]: (state, action) => {
state.playerList = {
status: 'idle',
data: {},
error: action.payload,
};
},
}
});
export default teamSlice;
import React from "react";
import { useSelector, useDispatch } from "react-redux";
import { fetchPlayerList } from './teamSlice';
const Team = (props) => {
const dispatch = useDispatch();
const playerList = useSelector((state: any) => state.team.playerList);
return (
<div>
<button
onClick={() => { dispatch(fetchPlayerList('1838315')); }}
>Fetch Team players</button>
<p>API status {playerList.status}</p>
<div>
{ (playerList.status !== 'loading' && playerList.data.length) &&
playerList.data.map((player) =>
<div style={{display: 'flex'}}>
<p>Name: {player.name}</p>
<p>Games Played: {player.games_played}</p>
</div>
)
}
</div>
</div>
)
}
export default Team;