【问题标题】:React State Manipulated from Another File Without Reference在没有参考的情况下从另一个文件操作的反应状态
【发布时间】:2022-01-06 00:11:39
【问题描述】:

我正在学习关于 Udemy 的 React 课程。在这个模块中,我们有一个简单的任务应用程序来演示自定义钩子。我遇到过在 App.js 文件中管理“任务”状态的情况,“useHttp”自定义钩子有一个函数“fetchTasks”,当在 App.js 中调用时,它接受“transformTasks”作为参数。我遇到的问题是“transformTasks”操纵了 App.js 中的“任务”状态,但它实际上是在“useHttp”自定义钩子中被调用和执行的。真的很想帮助理解它是如何工作的机制。在没有传入状态的情况下从另一个文件调用时如何操作状态?该代码确实按预期工作。这是完整应用程序的 github 链接,以下是两个相关文件:https://github.com/yanichik/react-course/tree/main/full-course/custom-hooks-v2

这里是 App.js 文件:

import React, { useEffect, useMemo, useState } from "react";
import Tasks from "./components/Tasks/Tasks";
import NewTask from "./components/NewTask/NewTask";
import useHttp from "./custom-hooks/useHttp";

function App() {
    // manage tasks state here at top level
    const [tasks, setTasks] = useState([]);

    const myUrl = useMemo(() => {
        return {
            url: "https://react-http-104c4-default-rtdb.firebaseio.com/tasks.json",
        };
    }, []);

    const { isLoading, error, sendRequest: fetchTasks } = useHttp();

    useEffect(() => {
        // func transforms loaded data to add id (firebase-generated), push to loadedTasks, then
        // push to tasks state
        const transformTasks = (taskObj) => {
            let loadedTasks = [];
            for (const taskKey in taskObj) {
                loadedTasks.push({ id: taskKey, text: taskObj[taskKey].text });
            }
            setTasks(loadedTasks);
        };
        fetchTasks(myUrl, transformTasks);
        // if you add fetchTasks as a dependency this will trigger a re-render each time states
        // are set inside sendRequest (ie fetchTasks) and with each render the custom hook (useHttp)
        // will be recalled to continue the cycle. to avoid this, wrap sendRequest with useCallback
    }, [fetchTasks, myUrl]);

    const addTaskHandler = (task) => {
        setTasks((prevTasks) => prevTasks.concat(task));
    };
    return (
        <React.Fragment>
            <NewTask onEnterTask={addTaskHandler} />
            <Tasks
                items={tasks}
                loading={isLoading}
                error={error}
                onFetch={fetchTasks}
            />
        </React.Fragment>
    );
}

export default App;

这里是“useHttp”自定义钩子:

import { useState, useCallback } from "react";

// NOTE that useCallback CANNOT be used on the top level function
function useHttp() {
    const [isLoading, setIsLoading] = useState(false);
    const [error, setError] = useState(null);

    const sendRequest = useCallback(async (httpConfig, applyFunction) => {
        setIsLoading(true);
        setError(false);
        try {
            const response = await fetch(httpConfig.url, {
                method: httpConfig.method ? httpConfig.method : "GET",
                headers: httpConfig.headers ? httpConfig.headers : {},
                body: httpConfig.body ? JSON.stringify(httpConfig.body) : null,
            });
            // console.log("response: " + response.method);

            if (!response.ok) {
                throw new Error("Request failed!");
            }

            const data = await response.json();
            
            applyFunction(data);
            // console.log("the formatted task is:" + applyFunction(data));
        } catch (err) {
            setError(err.message || "Something went wrong!");
        }
        setIsLoading(false);
    }, []);
    return { sendRequest, isLoading, error };
}

export default useHttp;

【问题讨论】:

    标签: javascript reactjs react-hooks


    【解决方案1】:

    听起来您正在从一门体面的课程中学习。该钩子使用一种称为“组合”的技术。它知道您在获取数据后需要对数据进行一些处理,然后让您传入(applyFunction 变量)您自己的 sn-p 代码来进行处理。

    您的 sn-p 代码只是一个函数,但各方都同意该函数采用的参数。 (这是使用 typescript 帮助捕获错误的地方。)

    所以你传入一个你编写的函数,你的函数有 1 个参数,你期望它是下载的数据。

    useHttp 钩子会记住你的函数,一旦它下载了数据,它就会调用你的函数并传入数据。

    如果你在传递给钩子的函数中使用了一些你自己的变量,它们会被及时冻结……有点。这罐虫子是一个名为“闭包”的主题,如果还没有,我相信它会在课程中出现。

    【讨论】:

      猜你喜欢
      • 2018-12-28
      • 1970-01-01
      • 2016-01-08
      • 2019-12-15
      • 2017-04-22
      • 1970-01-01
      • 2017-07-20
      • 1970-01-01
      • 2019-01-22
      相关资源
      最近更新 更多