如何正确使用 useReducer ? (反应钩子)

时间:2021-01-27 16:04:17

标签: reactjs react-hooks use-reducer

我很确定我没有正确使用 useReducer 有一个例子:

**//My array with some items**    
const items = [
        {
          id: 0,
          title: "Cidre Doux",
          img:
            "img",
          type: "doux",
        },
        {
          id: 1,
          title: "Cidre demi-doux",
          img:
            "img",
          type: "demi-doux",
        },
   ]

**//UseState for passing category in dispatch**

const [categoryItem, setCategoryItem] = useState("");

**//useReducer**

const [state, dispatch] = useReducer(reducer, items);
  function reducer(state, action) {
    switch (action.type) {
      case "all":
        return [...items];

      case categoryItem:
        return items.map((item) =>
          item.type === categoryItem ? { ...item } : null
        );

      default:
        throw new Error();
    }
  }

**//function onClick**

  const dispatchCategory = (category) => {
    setCategoryItem(category);
    dispatch({ type: category });
  };

{...}

//Return

<button onClick={() => { dispatchCategory("doux");}}> Doux </button>

{...}

//My map

{state.map((item) => {
          if (item != null) {
            return <ShopCardItem key={item.id} {...item} />;
          } else {
            return "";
          }
        })}

在我的reducer 中,我使用items 而不是state,因为我有几个按钮可以找到一些类别对象。如果我使用状态我无法获得点击按钮后的所有项目。

如果我在函数 reducer 中使用 state 有一个例子:

步骤:一,点击“全部”=>所有项目,

步骤:二,点击“doux”=> doux items,

步骤:三,再次点击“全部”,只获得doux项目。

我该如何解决这个问题?

非常喜欢!

1 个答案:

答案 0 :(得分:0)

你在这里做什么没有意义。您的 items 是一个常数。您选择的类别通过 useState 存储(未存储在 reducer 状态)。为什么需要减速器?

你的 reducer 违反了 reducer 的一些基本原则,比如依赖外部状态。好消息是你的组件很容易修复,因为 reducer 几乎可以完全删除。我们要保留的逻辑是如何从类别状态派生当前项目。此筛选项列表是从状态派生的变量。它不需要存储在状态本身。

我们看categoryItem。如果为空,则currentItems 是所有项目,如果是类别,则currentItems 是与类别匹配的项目。我将使用 "" 来表示 all 而不是 "all",因为您的 useState 的初始值是 ""。无论您使用什么,保持一致

const currentItems = categoryItem === "" ? items : items.filter( item => item.type === categoryItem );

就是这样。所以现在删除整个useReducer。当您映射项目时,现在是 state.map 而不是 currentItems.map。您也可以删除 dispatchCategory 函数。使用 dispatchCategory("doux") 代替 setCategoryItem("doux")