How to dispatch in useEffect?

老子叫甜甜 提交于 2021-01-29 11:32:54

问题


I tried to set a state using useState inside useEffect with no problem, code as follows:

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;

Now I'd like to do the same thing but with useReducer, I tried to modify the above code to the following but no luck:

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;

How can I use useReducer in this case?


回答1:


You're setting the reducer with the same state property as it was before in this case you're basically doing:

title: state.title

And since your default state is a title with an empty array value you're not changing anything.

You need to use the action argument in your reducer to accomplish what you want:

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

And your dispatch should be something like this:

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



回答2:


Your useReducer call is not inside the function, therefore doesn't get attached to it. Call it like this:

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();
  }, []);
}

Also keep in mind that your useEffect runs every time the Banner function gets called. Consider adding a dependencies array as stated here in the hooks tutorial: https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects



来源:https://stackoverflow.com/questions/63836552/how-to-dispatch-in-useeffect

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!