وضعیت‌های غیرممکن در React – مدیریت پیش‌بینی‌پذیر وضعیت با useReducer

استفاده هم‌زمان از چند useState برای مدیریت وضعیت‌های مرتبط می‌تواند منجر به وضعیت‌های غیرممکن و باگ‌های پنهان شود. این مقاله نشان می‌دهد چگونه با ترکیب وضعیت‌های مرتبط در یک useReducer واحد، می‌توان از بروز چنین مشکلاتی جلوگیری کرد. با تعریف یک ساختار وضعیت پیچیده شامل داده، بارگذاری و خطا، و استفاده از اکشن‌های مشخص، مدیریت وضعیت در React پیش‌بینی‌پذیرتر و قابل اطمینان‌تر می‌شود.

impossible stateuseReducerstate managementcomplex reducer

~3 دقیقه مطالعه • بروزرسانی ۳۰ مهر ۱۴۰۴

مقدمه


در React، استفاده از چندین useState برای مدیریت وضعیت‌های مرتبط مانند داده، بارگذاری و خطا می‌تواند منجر به وضعیت‌های غیرممکن شود. برای مثال، ممکن است هم‌زمان پیام خطا و پیام «در حال بارگذاری» نمایش داده شوند. برای جلوگیری از این مشکل، می‌توان از useReducer استفاده کرد تا تمام وضعیت‌های مرتبط را در یک ساختار واحد مدیریت کنیم.


ترکیب وضعیت‌ها در 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 با وضعیت پیچیده


تابع 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 پیش‌بینی‌پذیرتر، خواناتر و قابل نگهداری‌تر باشد — به‌ویژه در سناریوهای پیچیده مانند دریافت داده‌های غیرهمزمان.


نوشته و پژوهش شده توسط دکتر شاهین صیامی