首页 > 解决方案 > 如何从 React 组件中重构异步函数

问题描述

我有一个简单的反应组件,看起来如此AllWords.js

import React, {  useEffect, useState } from 'react';
import consts from '../../constants/Constants.js';

function AllWords() {
  const [words, setWords] = useState([]);

  async function fetchData(){
    
    const response= await fetch(consts.FETCH_URL);
    const data = await (response.json());
    setWords(data);
  };

  // API:  useEffect( () => { . . . return cleanup; },[var_n_whose_change_triggers_useEffect . . .] );

  useEffect(() => {fetchData()}, [] );

    return (
    <>
    {
      words.map(w=> <div>{w.word}</div>)
    }
    </>
  );
}

export default AllWords;

我想将fetchData()组件中的方法重构到另一个文件中(基本上是一个.js包含 fetch 调用的单独文件)。

我想要的是创建一个标题为FetchAllWords.js&src/actions/然后导入它的文件。并使用它。

我有几个问题:

  1. 我需要设置stateinFetchAllWords.js然后useSelector提取状态AllWords.js吗?
  2. FetchAllWords.js是否需要usedispatch调度方法调用设置state?我想将其setState放入 FetchAllWords.js然后将其提取到AllWords.js. 这是我到目前为止所拥有的:
import consts from '../constants/Constants.js';
import {  useState } from 'react';


async function FetchAllWords(){
    const [words, setWords] = useState([]);
  
        const response= await fetch(consts.FETCH_URL);
        const data = await (response.json());
        setWords(data);
    
}
 

export default FetchAllWords;

我不确定如何导入它并在AllWords.js. 我正在使用以下语句: import wordList from '../../actions/FetchAllWords';

然后我尝试将其wordList用作文件的句柄'../../actions/FetchAllWords.js'并尝试访问async function FetchAllWordsso wordList.FetchAllWords()

首先,尽管导入调用,编辑器(VSCode)不会让我看到该功能。

其次,我收到一个错误(类似): TypeError: _actions_FetchAllWords_js__WEBPACK_IMPORTED_MODULE_3__.default.FetchAllWords is not a function

任何见解或帮助将不胜感激,因为 JS 和 React 相当不安。github 仓库是:https ://github.com/mrarthurwhite/hooks-p5-react-redux

编辑:根据大卫的建议:

所以AllWords.jsReact 组件是:

import React, {  useEffect, useState } from 'react';
import wordList from '../../services/Fetch.js';
function AllWords() {
  const [words, setWords] = useState([]);

  function fetchData(){
    
    wordList.fetchAllWords().then(
      data =>  setWords(data)
    );
  };

  // API:  useEffect( () => { . . . return cleanup; },[var_n_whose_change_triggers_useEffect . . .] );
  useEffect(() => {fetchData()}, [] );

    return (
    <>
    {
      words.map(w=> <div>{w.word}</div>)
    }
    </>
  );
}

export default AllWords;

并且Fetch.js是:

import consts from '../constants/Constants.js';

class Fetch { 

async fetchAllWords(){
        const response= await fetch(consts.FETCH_URL);
        const data = await (response.json());
        return data;
}
 
       
}
export default Fetch;

标签: javascriptreactjsreact-hooks

解决方案


不,不用担心外部文件中的状态。只关注它应该做的一件事,执行 AJAX 操作。在最简单的情况下,它只是一个函数,例如:

import consts from '../../constants/Constants.js';

const fetchAllWords = async () => {
    const response = await fetch(consts.FETCH_URL);
    const data = await (response.json());
    return data;
}

export default fetchAllWords;

如果您还计划添加其他服务操作,您甚至可以将其设为包含此功能的类。(获取特定单词?查找单词?等等。)关键是它只做一件事,提供数据。让 React 组件处理 React 状态。

在组件中,您只需使用它来获取数据。就像是:

import React, {  useEffect, useState } from 'react';
import fetchAllWords from '../../services/FetchAllWords.js';

function AllWords() {
  const [words, setWords] = useState([]);

  useEffect(() => {
    fetchAllWords().then(w => setWords(w));
  }, []);

  return (
    <>
    {
      words.map(w=> <div>{w.word}</div>)
    }
    </>
  );
}

export default AllWords;

总的来说,这是一个分离关注点的问题。该服务执行 AJAX 操作并返回有意义的数据,内部涉及诸如 JSON 反序列化之类的事情。React 组件维护状态并渲染输出,内部关注useEffect运行后更新状态等等。


推荐阅读