我很难全神贯注地以最佳方式从API一次(以及在首次请求时)获取数据,然后存储结果以供重用和/或其他组件功能。下面是一个useContext
和useReducer
的工作示例,但是对于这样一个“简单”的任务来说,它非常复杂。
有没有更好的方法?对于大量的API调用,实现此目标的最佳方法是什么。任何建议都将不胜感激。
import React from "react";
import ReactDOM from "react-dom";
import axios from 'axios';
const initialState = {
items: [],
itemsLoading: false
};
const actions = {
FETCHING_ITEMS: "FETCHING_ITEMS",
FETCHED_ITEMS: "FETCHED_ITEMS"
};
const reducer = (state, action) => {
switch (action.type) {
case actions.FETCHING_ITEMS:
return { ...state, itemsLoading: true, items: {} };
case actions.FETCHED_ITEMS:
return { ...state, items: action.value };
default:
return state;
}
};
const Context = React.createContext();
const Provider = ({ children }) => {
const [state, dispatch] = React.useReducer(reducer, initialState);
const value = {
items: state.items,
itemsLoading: state.itemsLoading,
fetchItems: () => {
if (!state.itemsLoading) {
dispatch({ type: actions.FETCHING_ITEMS });
axios
.get("https://jsonplaceholder.typicode.com/todos")
.then(function(response) {
dispatch({ type: actions.FETCHED_ITEMS, value: response.data });
});
}
}
};
return <Context.Provider value={value}>{children}</Context.Provider>;
};
const Filters = () => {
const { items, fetchItems } = React.useContext(Context);
React.useEffect(() => {
fetchItems();
}, [fetchItems]);
const listItems = items.length
? items.map(item => {
return <li key={item.id}>{item.title}</li>;
})
: "";
return (
<div>
<ul>{listItems}</ul>
</div>
);
};
const App = () => {
return (
<Provider>
<Filters />
</Provider>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(
<App />,
rootElement
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.2/axios.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
无法使代码段在SO上运行,这是一个有效的沙箱:https://codesandbox.io/s/falling-frog-4pdm1
谢谢!
答案 0 :(得分:1)
我想您可以使用custom hooks-
对此进行一些抽象int main()
{
char arr[] = { "Q, R, Y, M, N, L, O" };
int n = sizeof(arr) / sizeof(arr[0]);
insertionSort(arr, n);
printArray(arr, n);
return 0;
}
您很兴奋,所以您可以立即开始使用它-
const identity = x => x
const useAsync = (runAsync = identity, deps = []) => {
const [loading, setLoading] = useState(true)
const [error, setError] = useState(null)
const [result, setResult] = useState(null)
useEffect(_ => {
Promise.resolve(runAsync(...deps))
.then(setResult, setError)
.finally(_ => setLoading(false))
}, deps)
return { loading, error, result }
}
但是到此为止。在需要时编写更多有用的钩子-
const MyComponent = () => {
const { loading, error, result:items } =
useAsync(_ => {
axios.get("path/to/json")
.then(res => res.json())
}, ...)
// ...
}
方便地useEffect仅在依赖项更改时才重新运行效果。但是,如果您希望通过更精细的控制来处理昂贵的查询,请查看useCallback和useMemo。