در React، استفاده از چندین useState برای مدیریت وضعیتهای مرتبط مانند داده، بارگذاری و خطا میتواند منجر به وضعیتهای غیرممکن شود. برای مثال، ممکن است همزمان پیام خطا و پیام «در حال بارگذاری» نمایش داده شوند. برای جلوگیری از این مشکل، میتوان از useReducer استفاده کرد تا تمام وضعیتهای مرتبط را در یک ساختار واحد مدیریت کنیم.
بهجای استفاده از چندین useState، از یک useReducer با وضعیت اولیهٔ پیچیده استفاده میکنیم:
const [stories, dispatchStories] = React.useReducer(
storiesReducer,
{ data: [], isLoading: false, isError: false }
);در useEffect، وضعیت بارگذاری و موفقیت یا شکست را با dispatch کردن اکشنها مدیریت میکنیم:
dispatchStories({ type: 'STORIES_FETCH_INIT' });
fetch(`${API_ENDPOINT}react`)
.then((response) => response.json())
.then((result) => {
dispatchStories({
type: 'STORIES_FETCH_SUCCESS',
payload: result.hits,
});
})
.catch(() =>
dispatchStories({ type: 'STORIES_FETCH_FAILURE' })
);تابع reducer باید تمام انتقالهای وضعیت را پوشش دهد:
const storiesReducer = (state, action) => {
switch (action.type) {
case 'STORIES_FETCH_INIT':
return { ...state, isLoading: true, isError: false };
case 'STORIES_FETCH_SUCCESS':
return { ...state, isLoading: false, isError: false, data: action.payload };
case 'STORIES_FETCH_FAILURE':
return { ...state, isLoading: false, isError: true };
case 'REMOVE_STORY':
return {
...state,
data: state.data.filter(
(story) => action.payload.objectID !== story.objectID
),
};
default:
throw new Error();
}
};در JSX، وضعیتها را از شیء stories استخراج میکنیم:
{stories.isError && <p>Something went wrong ...</p>}
{stories.isLoading ? (
<p>Loading ...</p>
) : (
<List list={searchedStories} onRemoveItem={handleRemoveStory} />
)}با ترکیب وضعیتهای مرتبط در یک useReducer و تعریف اکشنهای مشخص، میتوان از بروز وضعیتهای غیرممکن در رابط کاربری جلوگیری کرد. این روش باعث میشود مدیریت وضعیت در React پیشبینیپذیرتر، خواناتر و قابل نگهداریتر باشد — بهویژه در سناریوهای پیچیده مانند دریافت دادههای غیرهمزمان.