我正在使用 Robin Wieruch 的出色工作来了解如何调用 API 端点。这是他的一个项目:https ://github.com/the-road-to-learn-react/react-hooks-introduction
下图是他的修改版useDataApiHook-example
。有了它,我连接了两个按钮,然后给了我 3 种查询端点的方法。我选择在所有情况下都使用相同的端点,但用不同的端点对其进行了测试,它似乎工作正常。
import React, {
Fragment,
useState,
useEffect,
useReducer,
} from 'react';
import axios from 'axios';
const dataFetchReducer = (state, action) => {
switch (action.type) {
case 'FETCH_INIT':
return { ...state, isLoading: true, isError: false };
case 'FETCH_SUCCESS':
return {
...state,
isLoading: false,
isError: false,
data: action.payload,
};
case 'FETCH_FAILURE':
return {
...state,
isLoading: false,
isError: true,
};
default:
throw new Error();
}
};
export const useDataApi = (initialUrl, initialData) => {
console.log('Starting useDataApi');
const [url, setUrl] = useState(initialUrl);
const [state, dispatch] = useReducer(dataFetchReducer, {
isLoading: false,
isError: false,
data: initialData,
});
useEffect(() => {
let didCancel = false;
const fetchData = async () => {
console.log('Dispatching FETCH_INIT');
dispatch({ type: 'FETCH_INIT' });
try {
const result = await axios(url);
if (!didCancel) {
console.log('Dispatching FETCH_SUCCESS');
dispatch({ type: 'FETCH_SUCCESS', payload: result.data });
}
} catch (error) {
if (!didCancel) {
console.log('Dispatching FETCH_FAILURE');
dispatch({ type: 'FETCH_FAILURE' });
}
}
};
fetchData();
return () => {
didCancel = true;
};
}, [url]);
return [state, setUrl];
};
function App() {
const [query, setQuery] = useState('redux');
const [{ data, isLoading, isError }, doFetch] = useDataApi(
'http://hn.algolia.com/api/v1/search?query=redux',
{ hits: [] },
);
const handleTestButton1Click = (event) => {
console.log('Test Button 1 pressed');
doFetch(
'http://hn.algolia.com/api/v1/search?query=canada',
);
};
const handleTestButton2Click = (event) => {
console.log('Test Button 2 pressed');
doFetch(
'http://hn.algolia.com/api/v1/search?query=germany',
);
};
return (
<Fragment>
<form
onSubmit={event => {
doFetch(
`http://hn.algolia.com/api/v1/search?query=${query}`,
);
event.preventDefault();
}}
>
<input
type="text"
value={query}
onChange={event => setQuery(event.target.value)}
/>
<button type="submit">Search</button>
</form>
<div>
<button type="button" onClick={() => handleTestButton1Click()}>Test 1</button>
<button type="button" onClick={() => handleTestButton2Click()}>Test 2</button>
</div>
{isError && <div>Something went wrong ...</div>}
{isLoading ? (
<div>Loading ...</div>
) : (
<ul>
{data.hits.map(item => (
<li key={item.objectID}>
<a href={item.url}>{item.title}</a>
</li>
))}
</ul>
)}
</Fragment>
);
}
export default App;
我有几个问题:
- 假设我不想在组件加载时调用查询(并且不想在加载时发出 GET 请求)。如何做到这一点?
- 想象一下,按钮 1 和 2 触发的事件实际上分别是对不同 API 端点的调用。例如,按钮 1 可以代表一个调用,以查明刚刚输入的特定用户名是否已经存在。按钮 2 可以代表一个呼叫,以查明刚刚输入的电子邮件地址是否已经存在。在这种情况下,确保正确使用new
data
填充的常见做法是什么?doFetch
如果问题 2 不清楚,让我换一种说法:在所有情况下,data
对象都由useDataApi
. 但是,如果第一次调用useDataApi
是为了填充一个东西,第二次调用是为了填充其他东西,第三次调用是为了再次填充其他东西,那么处理这种逻辑的最佳方法是什么?