如何在自定义react useEffect

时间:2019-11-12 12:30:11

标签: javascript reactjs axios react-router-v4 use-effect

我有两个正在使用的组件。在第一个组件中,我制作了一个自定义useEffect钩子,该钩子从服务器中检索数据。请参见下面的代码:

一个代码段

import {useState, useCallback} from 'react';
import {stageQuizApi} from '../api/quiz';
import {QuestionService} from "../services/IdDbServices/question_service";


const usePostData = ({url, payload, config}) => {
    const [res, setRes] = useState({data: null, error: null, isLoading: false});


    const callAPI = useCallback(() => {
         setRes(prevState => ({...prevState, isLoading: true}));
         stageQuizApi.patch(url, payload, config).then( res => {
          setRes({data: res.data, isLoading: false, error: null});
          const questionInDb = {};

              const {NoTimePerQuestion,anwser, question, playerDetails, option} = res.data.data;
              const {playerid,anwserRatio, name} = playerDetails
              questionInDb.timePerQuestion = NoTimePerQuestion;
              questionInDb.anwserRatio = anwserRatio;
              questionInDb.options = option;
              questionInDb.answer = anwser;
              questionInDb.playerId = playerid;
              questionInDb.name = name;
              questionInDb.question = question;
              const Service = new QuestionService();
              Service.addStudent(questionInDb).
            then(response=>console.log(response))
            .catch(err=>console.log(err));

         }).catch((error) => {
           console.log(error)
            if (error.response) {
               const errorJson = error.response.data
               setRes({data: null, isLoading: false, error: errorJson.message});
             } else if (error.request) {
               setRes({data: null, isLoading: false, eror: error.request});
             } else {
               setRes({data: null, isLoading: false, error: error.message});
             }
         })
    }, [url, config, payload])
    return [res, callAPI];
}

export default usePostData;


以上模块具有双重目的。它首先向我的端点发出axios请求,其次向浏览器IndexDb插入数据库(类似于localstorage,但使用sql方法)(例如使用从第一个请求获得的响应将数据插入数据库。因此通常我有一个 .then 外部的诺言部分。

第二个代码段

const questionInDb = {};

              const {NoTimePerQuestion,anwser, question, playerDetails, option} = res.data.data;
              const {playerid,anwserRatio, name} = playerDetails
              questionInDb.timePerQuestion = NoTimePerQuestion;
              questionInDb.anwserRatio = anwserRatio;
              questionInDb.options = option;
              questionInDb.answer = anwser;
              questionInDb.playerId = playerid;
              questionInDb.name = name;
              questionInDb.question = question;
              const Service = new QuestionService();
              Service.addStudent(questionInDb).
            then(response=>console.log(response))
            .catch(err=>console.log(err));

这是问题所在,我试图保持状态,因为我希望该模块的结果在另一条路线中共享,并且我不想再次击中服务器,因此我将结果插入了indexDb浏览器存储中。这是执行上述模块的代码:

代码段三

const displaySingleQuestion = ()=>{
    OnUserGetQuestion();
      history.push('/player/question');
  }

上述方法是从我的第一条路线 /question 中调用的,并且当时,可以将用户重定向到 /player/question displaySingleQuestion 被调用。

然后在新路径 /player/question 上,我想从IndexDb中获取数据并使用下面的useEffect代码更新该组件的状态:

第四代码段

useEffect(()=>{
      const getAllUserFromIndexDb = async()=>{
        try{

          const result = await new Promise((resolve, reject) => {
            service.getStudents().then(res=>resolve(res)).catch(err=>reject(err))
          });


          console.log('it did not get to the point i was expecting',result)

          if(result[0]){
            console.log('it got to the point i was expecting')
            const singleQuestion = result[0];
            const questionPage = playerQuestionToDisplay;
            questionPage.name = singleQuestion.name;
            questionPage.anwserRatio = singleQuestion.anwserRatio;
            questionPage.answer = singleQuestion.answer;
            questionPage.options = singleQuestion.options;
            questionPage.playerId = singleQuestion.playerId;
            questionPage.question = singleQuestion.question;
            questionPage.timePerQuestion = singleQuestion.timePerQuestion;
           return setplayerQuestionToDisplay({playerQuestionToDisplay:questionPage})
          }
        }
        catch(error){
          console.log(error)
        }


      }

      getAllUserFromIndexDb();

      return function cleanup() {
        setplayerQuestionToDisplay({playerQuestionToDisplay:{}})
      }

    },[history.location.pathname]);

问题在于,只有一个按钮单击(代码段三)( displaySingleQuestion() )会触发整个功能并重定向到 {{ 1}} 页面,但是在这种新的方式下,直到重新加载页面后才设置状态,我尝试调试问题,发现单击按钮时我发现了代码段最后执行两次,因此在运行第四代码段时,它处于承诺状态,直到页面重新加载发生为止,该组件的状态为 undefined

感谢您的阅读,对于解决此问题,我将不胜感激。

0 个答案:

没有答案