【问题标题】:Why my useState function from Context not work为什么我的 Context 中的 useState 函数不起作用
【发布时间】:2021-07-13 05:42:44
【问题描述】:

当我使用 useEffect 钩子时,我学习了 react 并且在 setMethode 上遇到了一些问题。

在我的程序中,我在 react 和数据库 postgres 之间创建了一个连接。通过该连接,我从数据库中获取数据并将其作为 JSON 文件发送到我的前端应用程序。这是我的 server.js


const express = require("express");
const cors = require("cors");
const db = require("./db");
const app = express();


const port = 3005;

//Das ist die middelware, dass anfragen vor den anfragen get post put delet bearbeitet
app.use(
    cors(),
    express.json()//Wird gebraucht um den body zu definieren bzw. json files zu empfangen
);




//Funktion listen hat (portnummer, callbackfunktion)
app.listen(port, ()=>{ 
 
    console.log("Server is up and listining on Port: " + port);
    });

app.get("/getRestaurants/:id", async (req, res) =>{
    try{
        console.log("Get One");
        const restaurants = await db.query("select * from restaurants where id = $1",[req.params.id]);
        //console.log(result.rows[0].restaurant_name);
        
        const reviews = await db.query("select * from reviews where restaurantid = $1",[req.params.id]);
        res.status(200).json({
            success:"true",
            data:{
                restaurants: restaurants.rows[0],
                reviews: reviews.rows
            },
        });
        console.log("works");
    }
    catch(err){
        console.log(err);
    }
})

通过 Context.jsx 文件中的列表,我保存数据库中的值并将其用于我的前端应用程序。这是我的 Context.jsx

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

export const RestaurantsContext = createContext();

export const RestaurantsContextProvider = props =>{

    //Definition einer Liste mit []
    const [restaurants, setRestaurants] = useState([]);
    const [selectedRestaurant, setSelectedRestaurant] = useState(null);

    //Hier wir din einem Hook die function setRestaurants benutzt um "restaurants" zu verändern, mit einem array
    const addRestaurant =(newRestaurant)=>{
        //...restaurants kopiert die Werte und fügt newRestaurant ein
        setRestaurants([...restaurants, newRestaurant]);
    }
    return(
        <RestaurantsContext.Provider value = {{restaurants: restaurants,//variable
                                             setRestaurants,            //funktion
                                            addRestaurant,              //funktion
                                            selectedRestaurant,         //variable
                                            setSelectedRestaurant       //funktion
                                            }}>    //
            {props.children}
        </RestaurantsContext.Provider>
    )

}

要使用我在 Context 中实现的这个函数和变量,我必须在我的下一个 JSX 文件中导入它。这就是 RestaurantDetailedPage。在此页面中,我想获取有关评论和餐厅的信息。所以我使用 UseEffect 挂钩从我的数据库中获取 Dadas 并将其保存在来自 Cotext 的列表中。您可以在我的以下代码中看到它。

import React, { useContext, useEffect } from 'react';
import { useParams } from 'react-router';
import RestaurantFinder from '../api/RestaurantFinder';
import { RestaurantsContext } from "../context/RestaurantsContext";
import Reviews from '../components/Reviews';
import StarComponent from '../components/StarComponent';
import AddReview from '../components/AddReview';


const RestaurantDetaiiledPage = () =>{

    const{ selectedRestaurant, setSelectedRestaurant}= useContext(RestaurantsContext);
    const {id} = useParams();

        useEffect(async()=>{
            
            try{
                
                const result = await RestaurantFinder.get("/"+id);
                 console.log(result);
                 //Bekommt restaurant und reviews
                 setSelectedRestaurant(result.data.data);
                 console.log("useEffect");
                 console.log(selectedRestaurant); 
             }catch(err){}

        }, []);//Wichtig, damit es nur 1x

    return(
        <div>{selectedRestaurant && (
            <>    
                
                <div>{<Reviews reviewsObject = {selectedRestaurant.reviews}/>}</div>
                <div>{<AddReview/>}</div>
                </>
                )}
        </div>
        )

        

}

export default RestaurantDetaiiledPage;

在我的图片上,您可以看到 consol.log(result)from 结果

所以我从我的数据库中获取数据。但是为什么我的函数 setSelectedRestaurant 不适用于命令 setSelectedRestaurant(result.data.data); 我的程序就在此时停止。我没有从我的 console.log("useEffect") 得到“useEffect”输出。

希望你能帮助我

【问题讨论】:

  • 您的代码中存在许多问题:您无法将异步函数传递给 useEffect,您在花括号内使用 JSX 标签等。
  • 我只是按照教程并尝试独立完成。所以我不只是复制粘贴
  • 好的,我有解决方案。我必须先使用两个 useEffects 重新渲染两次:useEffect(()=&gt;{setSelectedRestaurant(result.data.data)},[] 第二:useEffect(()=&gt;{console.log(selectedRestaurant)},[selectedRestaurant] 并且它有效

标签: javascript node.js reactjs database


【解决方案1】:

好的,我发现了错误。我在课堂评论中有错字。无论如何,我想提供一些有关更新我的价值selectedRestaurant的信息。

要更新变量selectedRestaurant,我必须使用异步的函数setSelectedRestaurant。由于异步性,我必须使用第二个 useEffect 钩子再次渲染它。

所以在我的第一个 useEffect 挂钩中,我更改了 selectedRestaurant 的值,并且由于我的方括号,它只调用一次。

        useEffect(()=>{
            
           const fetchData = async(id)=>{
                
                const result = await RestaurantFinder.get("/"+id);
                console.log(result);
                setSelectedRestaurant(result.data.data);  
            }
        fetchData();
        }, []);//Invoke only once

如果selectedRestaurant 的值发生了变化,我会再次渲染并调用第二个useEffect。所以代码看起来像:

useEffect(()=>{
          //Do something like:
          if(selectedRestaurant !== null){
          console.log("Selected Restaurant:", selectedRestaurant);
          }
        },[selectedRestaurant]);//Invokes if the value of selectedRestaurant has changed

再一次,它并没有解决我的问题,因为我有一点错字,但很高兴知道。 另外,我对反应还很陌生,希望我解释得对。

【讨论】:

    【解决方案2】:

    正如 Bob 大叔在 Clean Code 中所说,这段代码闻起来不太香。这里有一堆问题,其中一个肯定是你所说的。

        useEffect(async()=>{            
            try{                
                const result = await RestaurantFinder.get("/"+id);
                 console.log(result);
                 //Bekommt restaurant und reviews
                 setSelectedRestaurant(result.data.data);
                 console.log("useEffect");
                 console.log(selectedRestaurant); 
             }catch(err){}
    
        }, []);
    

    你的 try-catch 没用,我们可以删除它

        useEffect(async()=>{                         
                const result = await RestaurantFinder.get("/"+id);
                 console.log(result);
                 setSelectedRestaurant(result.data.data);
                 console.log("useEffect");
                 console.log(selectedRestaurant);
        }, []);
    

    回调不需要异步,阅读here,Dan Ambromv 是 react 的维护者之一

      useEffect(() => {
        const fetchRestaurant = async (id) => {
          const result = await RestaurantFinder.get("/" + id);
          console.log(result);
          setSelectedRestaurant(result.data.data);
          console.log("useEffect");
        };
        fetchRestaurant(id);
      }, [id]);
    

    除非您只想在我们的第一次渲染中使用它,否则没关系,但您的 useEffect 取决于 id 变量,这可能会改变。 另外,删除了console.log(selectedRestaurant);,因为setState是一个异步函数,所以selectedRestaurant的值不能改变

    我创建了这个流程的一个简单示例,它可以工作

    https://codesandbox.io/s/awesome-violet-fr7np?file=/src/App.js

    【讨论】:

    • 我已经更改了我的代码,但我仍然无法正常工作。功能 setSelectedRestaurant 不起作用。在您编写的程序中,我也收到错误
    【解决方案3】:

    useContext 语法错误。

    错误: const{ selectedRestaurant, setSelectedRestaurant}= useContext(RestaurantsContext); 正确的: const selectedRestaurant = useContext(RestaurantsContext); 换句话说,setSelectedRestaurant 不是一个函数。

    【讨论】:

    • OP 正在向上下文提供一个对象,并且正在解构该对象的属性。这不是问题。
    猜你喜欢
    • 2021-07-14
    • 2023-01-17
    • 1970-01-01
    • 2021-03-21
    • 2021-12-18
    • 2011-06-23
    • 1970-01-01
    • 2017-08-18
    • 2010-10-18
    相关资源
    最近更新 更多