useEffect 中如何调度?

How to dispatch in useEffect?

我试过在useEffect里面用useState设置状态没问题,代码如下:

import React, {useState, useEffect} from 'react';

const Banner = () => {
  const [title, setTitle] = useState([]);
  
  useEffect(() => {
    async function fetchData() {
      const api = 'some api url';
      let response = await fetch(api);
      response = await response.json();
      setTitle(response.title);
    }
    fetchData();
  })
}

export default Banner;

现在我想做同样的事情但是使用 useReducer,我尝试将上面的代码修改为以下但没有成功:

import React, {useState, useEffect} from 'react';

const bannerReducer = (state, action) => {
  switch(action.type) {
    case 'setTitle':
      return {
        ...state,
        title: state.title
      }
  }
}

const [state, dispatch] = useReducer(bannerReducer, {title: []});

const Banner = () => {
  const [title, setTitle] = useState([]);

  useEffect(() => {
    async function fetchData() {
      const api = 'some api url';
      let response = await fetch(api);
      response = await response.json();
      dispatch({type: 'setTitle', response.title});
    }
    fetchData();
  })
}

export default Banner;

在这种情况下如何使用 useReducer?

您的 useReducer 调用不在函数内部,因此不会附加到它。 像这样称呼它:

const Banner = () => {
  const [title, setTitle] = useState([]);
  const [state, dispatch] = useReducer(bannerReducer, {title: []});

  useEffect(() => {
    async function fetchData() {
      const api = 'some api url';
      let response = await fetch(api);
      response = await response.json();
      dispatch({type: 'setTitle', response.title});
    }
    fetchData();
  }, []);
}

另请记住,您的 useEffect 会在每次调用 Banner 函数时运行。考虑添加依赖项数组,如 hooks 教程中所述:https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects

您将减速器设置为与之前相同的状态 属性 在这种情况下,您基本上是在做:

title: state.title

并且由于您的默认状态是具有空数组值的标题,因此您无需更改任何内容。

您需要在 reducer 中使用 action 参数来完成您想要的:

const bannerReducer = (state, action) => {
 switch(action.type) {
  case 'setTitle':
   return {
    ...state,
    title: action.title
   }
  }
}

你的调度应该是这样的:

dispatch({type: 'setTitle', title: response.title});