一种在不使用 redux-thunk 或 redux-saga 中间件的情况下处理 Redux 存储上的异步状态更新的方法?
A way to handle async state updates on Redux store without using redux-thunk or redux-saga middleware?
我完全赞成不解决你没有的问题。
所以我开始学习和使用没有 Redux 的 React。
但现在我的应用程序状态已经增长,我开始面临一些状态管理问题。
越来越难处理了,我的App.js
满满的<SomeContext.Provider's>
。
所以我现在愿意将 Redux 添加到我的应用程序中。
但我当然会进行大量 API 调用以获取我的应用程序状态 的数据。因此,根据我的研究,基本上我有 异步状态更新的两个主要选项: redux-thunk
和 redux-saga
.
它们都添加了繁琐的样板文件和新的概念来处理和维护。
但我的问题是:我真的需要它们吗(thunk 或 saga)?
我编写的这段代码似乎可以工作,它使用异步数据更新商店。
结果:
https://codesandbox.io/s/ecstatic-antonelli-9cu7m
代码:
基本上我有这个减速器:
getApiDataReducer.js
const initialState = {
loading: false,
error: null,
data: null
};
function getApiDataReducer(state = initialState, action) {
switch (action.type) {
case "GET_DATA_START":
return {
...initialState,
loading: true
};
case "GET_DATA_SUCCESS":
return {
...initialState,
loading: false,
data: action.payload
};
case "GET_DATA_FAIL":
return {
...initialState,
loading: false,
error: action.payload
};
default:
return state;
}
}
export default getApiDataReducer;
rootReducer.js
import getApiDataReducer from "./getApiDataReducer";
import { combineReducers } from "redux";
const rootReducer = combineReducers({
getApiData: getApiDataReducer
});
export default rootReducer;
我的 index.js 文件和我的 App 组件:
import React from "react";
import ReactDOM from "react-dom";
import { createStore } from "redux";
import { Provider, useSelector, useDispatch } from "react-redux";
import rootReducer from "./reducers/rootReducer";
import "./styles.css";
const store = createStore(rootReducer);
function mockAPIcall() {
return new Promise((resolve, reject) => {
setTimeout(() => resolve("DATA FROM API"), 1000);
});
}
function mockAPIcallError() {
return new Promise((resolve, reject) => {
setTimeout(() => reject("SOMETHING WRONG HAPPENED"), 1000);
});
}
function App() {
const { loading, error, data } = useSelector(state => state.getApiData);
const dispatch = useDispatch();
async function getAsyncData() {
dispatch({ type: "GET_DATA_START" });
try {
const newData = await mockAPIcall();
dispatch({ type: "GET_DATA_SUCCESS", payload: newData });
} catch (err) {
dispatch({ type: "GET_DATA_FAIL", payload: err });
}
}
async function getAsyncDataError() {
dispatch({ type: "GET_DATA_START" });
try {
const newData = await mockAPIcallError();
dispatch({ type: "GET_DATA_SUCCESS", payload: newData });
} catch (err) {
dispatch({ type: "GET_DATA_FAIL", payload: err });
}
}
return (
<div>
<div>
Data:
{
loading ? "Loading..."
: error ? error
: data ? data
: "No data yet..."
}
</div>
<button onClick={getAsyncData}>Get Async Data</button>
<button onClick={getAsyncDataError}>Get Async Error</button>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
rootElement
);
问题:
我很确定那些库(redux-thunk
和 redux-saga
)可以做的远不止这些。因此,我想知道通过采用这种更简单的模式,我失去了那些库的哪些关键特性。
因为到目前为止我在我的应用程序上所做的,我几乎可以将所有内容重构为这个模式。但我很确定我这样做会关闭一些未来的大门。
这似乎是一个开放式问题,但我认为不是。 人们使用这些库,他们应该能够分辨出在使用此模式时未考虑哪些重要功能。
您正在以纯同步方式使用 Redux(使其免受 Redux 无论如何不支持的任何异步性的影响)并且缺少 Separation of Concerns 设计原则提供的好处。
OP 编辑: 这篇文章对我帮助很大:Separation of concerns design principle in Redux using redux-saga
我完全赞成不解决你没有的问题。
所以我开始学习和使用没有 Redux 的 React。
但现在我的应用程序状态已经增长,我开始面临一些状态管理问题。
越来越难处理了,我的App.js
满满的<SomeContext.Provider's>
。
所以我现在愿意将 Redux 添加到我的应用程序中。
但我当然会进行大量 API 调用以获取我的应用程序状态 的数据。因此,根据我的研究,基本上我有 异步状态更新的两个主要选项: redux-thunk
和 redux-saga
.
它们都添加了繁琐的样板文件和新的概念来处理和维护。
但我的问题是:我真的需要它们吗(thunk 或 saga)?
我编写的这段代码似乎可以工作,它使用异步数据更新商店。
结果:
https://codesandbox.io/s/ecstatic-antonelli-9cu7m
代码:
基本上我有这个减速器:
getApiDataReducer.js
const initialState = {
loading: false,
error: null,
data: null
};
function getApiDataReducer(state = initialState, action) {
switch (action.type) {
case "GET_DATA_START":
return {
...initialState,
loading: true
};
case "GET_DATA_SUCCESS":
return {
...initialState,
loading: false,
data: action.payload
};
case "GET_DATA_FAIL":
return {
...initialState,
loading: false,
error: action.payload
};
default:
return state;
}
}
export default getApiDataReducer;
rootReducer.js
import getApiDataReducer from "./getApiDataReducer";
import { combineReducers } from "redux";
const rootReducer = combineReducers({
getApiData: getApiDataReducer
});
export default rootReducer;
我的 index.js 文件和我的 App 组件:
import React from "react";
import ReactDOM from "react-dom";
import { createStore } from "redux";
import { Provider, useSelector, useDispatch } from "react-redux";
import rootReducer from "./reducers/rootReducer";
import "./styles.css";
const store = createStore(rootReducer);
function mockAPIcall() {
return new Promise((resolve, reject) => {
setTimeout(() => resolve("DATA FROM API"), 1000);
});
}
function mockAPIcallError() {
return new Promise((resolve, reject) => {
setTimeout(() => reject("SOMETHING WRONG HAPPENED"), 1000);
});
}
function App() {
const { loading, error, data } = useSelector(state => state.getApiData);
const dispatch = useDispatch();
async function getAsyncData() {
dispatch({ type: "GET_DATA_START" });
try {
const newData = await mockAPIcall();
dispatch({ type: "GET_DATA_SUCCESS", payload: newData });
} catch (err) {
dispatch({ type: "GET_DATA_FAIL", payload: err });
}
}
async function getAsyncDataError() {
dispatch({ type: "GET_DATA_START" });
try {
const newData = await mockAPIcallError();
dispatch({ type: "GET_DATA_SUCCESS", payload: newData });
} catch (err) {
dispatch({ type: "GET_DATA_FAIL", payload: err });
}
}
return (
<div>
<div>
Data:
{
loading ? "Loading..."
: error ? error
: data ? data
: "No data yet..."
}
</div>
<button onClick={getAsyncData}>Get Async Data</button>
<button onClick={getAsyncDataError}>Get Async Error</button>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
rootElement
);
问题:
我很确定那些库(redux-thunk
和 redux-saga
)可以做的远不止这些。因此,我想知道通过采用这种更简单的模式,我失去了那些库的哪些关键特性。
因为到目前为止我在我的应用程序上所做的,我几乎可以将所有内容重构为这个模式。但我很确定我这样做会关闭一些未来的大门。
这似乎是一个开放式问题,但我认为不是。 人们使用这些库,他们应该能够分辨出在使用此模式时未考虑哪些重要功能。
您正在以纯同步方式使用 Redux(使其免受 Redux 无论如何不支持的任何异步性的影响)并且缺少 Separation of Concerns 设计原则提供的好处。
OP 编辑: 这篇文章对我帮助很大:Separation of concerns design principle in Redux using redux-saga