最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Where is the context state set in React Context? - Stack Overflow

programmeradmin1浏览0评论

I've created an app that stores user information in firebase.

The main profile page consumes the data via a hook that retrieves the data from firebase/storage. What I'm trying to do in this page is get the profile data from the hook and set the profile data in the actual context. I realize this may not be the right now but it's what's been prescribed by ChatGPT.

export const ProfileForm = () => {
  const [profile, setProfile] = useState({
    username: "",
    bio: "",
    gender: "",
    sexo: "",
    edu: "",
    drinking: "",
    smoking: "",
    dob: "",
  });
  const [showLogin, setShowLogin] = useState(false);
  const { userProfile, setUserProfile } = useGetUserProfile();
  const { userProfileContext, setUserProfileContext } = useUserProfile()

  useEffect(() => {
    if (userProfile) {
      setProfile(userProfileContext);
    }
  }, [userProfile, setUserProfile]);

  const { showAlert } = useContext(AlertContext);

  return (
    <>
      <form onSubmit={handleSubmit(onSubmit)} noValidate>
        <Box display="flex" justifyContent="flex-end" p={2}>
          <Button
            variant="contained"
            color="secondary"
            onClick={async () => {
              await signOut(auth);
              window.location.href = "/login";
            }}
            sx={{
              borderRadius: "50%",
              width: 80,
              height: 80,
            }}>
            <span role="img" aria-label="logout">
              Logout
            </span>
          </Button>
        </Box>
        <Box mt={0} display="flex" justifyContent="center">
          <img
            src={profilePlaceholder}
            alt="Profile Placeholder"
            style={{ maxWidth: "100%", height: "auto" }}
          />
          <Box sx={{ flexDirection: "column" }}>
            <Typography
              ml={2}
              fontSize={{ base: "sm", md: "lg" }}
              color="white"
              sx={{ fontSize: "2rem" }}>
              {profile?.username || ""}
            </Typography>
            <Button
              variant="contained"
              size="small"
              onClick={() => setShowLogin(true)}
              sx={{ marginTop: 2, background: "white", color: "black" }}>
              Edit Profile
            </Button>
          </Box>
        </Box>
        <Card
          variant="outlined"
          sx={{
            display: "flex",
            flexDirection: "column",
            gap: 2,
            p: 2,
            maxWidth: 300,
            margin: "20px auto 20px auto",
          }}>
          <FormControl>
            <TextField
              id="bio"
              label="User Bio"
              multiline
              autoFocus
              rows={4}
              value={profile?.bio || ""}
              name="bio"
              placeholder="Tell us about yourself"
              InputProps={{
                readOnly: true,
              }}
            />
          </FormControl>
          <FormControl required>
            <TextField
              label="*Date of birth"
              type="date"
              id="dob"
              name="dob"
              value={
                profile?.dob
                  ? new Date(profile?.dob).toISOString().split("T")[0]
                  : new Date().toISOString().split("T")[0]
              }
              InputProps={{
                readOnly: true,
              }}
            />
          </FormControl>
          <FormControl>
            <TextField
              id="gender"
              value={profile?.gender || ""}
              required
              fullWidth
              name="gender"
              label="Gender"
              InputProps={{
                readOnly: true,
              }}></TextField>
          </FormControl>
          <FormControl>
            <TextField
              id="sexo"
              value={profile?.sexo || ""}
              required
              fullWidth
              name="sexo"
              label="Sexual Orientation"
              InputProps={{
                readOnly: true,
              }}></TextField>
          </FormControl>
          <FormControl>
            <TextField
              id="edu"
              value={profile?.edu || ""}
              required
              label="Education"
              name="edu"
              InputProps={{
                readOnly: true,
              }}></TextField>
          </FormControl>
          <FormControl>
            <TextField
              id="drinking"
              required
              value={profile?.drinking || ""}
              label="Drinking"
              name="drinking"
              InputProps={{
                readOnly: true,
              }}></TextField>
          </FormControl>
          <FormControl>
            <TextField
              id="smoking"
              required
              value={profile?.smoking || ""}
              label="Smoking"
              name="smoking"
              InputProps={{
                readOnly: true,
              }}></TextField>
          </FormControl>
        </Card>
      </form>
      <EditProfileModal show={showLogin} close={() => setShowLogin(false)} />
    </>
  );
};

The profile page has an edit modal that edits the profile data and stores it in the backend.

MODAL

export const EditProfileModal = (props: any) => {
  const { userRef, setUserDbData } = usePostUserProfileToDb();
  const { userStorageData, setUserStorageData } = usePostUserProfileToStorage();
  const { userProfile, setUserProfile } = useGetUserProfile();

  const [profile, setProfile] = useState({
    username: "",
    bio: "",
    gender: "",
    sexo: "",
    edu: "",
    drinking: "",
    smoking: "",
    dob: "",
  });

  useEffect(() => {
    if (userProfile) {
      setProfile(userProfile);
    }
  }, [userProfile, setUserProfile]);

  
  const handleSubmit = async (e: any) => {
    e.preventDefault();
    try {
      setUserStorageData(profile);
      setUserDbData(profile);
      props.close();
    } finally {
      setIsSubmitting(false);
    }
  };

And here is the context.

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

const UserProfileContext = createContext(null);


export const UserProfileProvider = ({ children }) => {
  const [userProfileContext, setUserProfileContext] = useState(null);

  return (
    <UserProfileContext.Provider value={{ userProfile: userProfileContext, setUserProfile: setUserProfileContext }}>
      {children}
    </UserProfileContext.Provider>
  );
};

export const useUserProfile = () => {
  const context = useContext(UserProfileContext);
  if (!context) {
    throw new Error('useUserProfile must be used within a UserProfileProvider');
  }
  return context;
};

When I try to set the context in the hook I get the following error:

This expression is not callable.
  Type 'never' has no call signatures.
import { useEffect, useState } from "react";
import useGetUserId from "./useGetUserId";
import { app } from "../environments/environment";
import { doc, getDoc, getFirestore } from "firebase/firestore";
import { useUserProfile } from "../Context/UserProfileContext";

const useGetUserProfile = () => {
  type profile = {
    email: string;
    username: string;
    userBio: string;
    dob: Date;
    gender: string;
    sexo: string;
    education: string;
    drinkingHabits: string;
    smokingHabits: string;
  };

  const db = getFirestore(app);
  const userId: string | null = useGetUserId();
  const [isLoading, setIsLoading] = useState(true);
  const [userProfile, setUserProfile] = useState<any | null>(null);
  const { userProfileContext, setUserProfileContext } = useUserProfile()

  useEffect(() => {
    const userProfile = async () => {
      setIsLoading(true);
      try {
        const userRef = localStorage.getItem("PROFILE_INFO");
        if (userRef) {
          const profile: profile = JSON.parse(userRef);
          setUserProfile(profile);
          setUserProfileContext(profile)
        } else {
          if (userId) {
            const id = JSON.parse(userId);
            const userRef = await getDoc(doc(db, "users", id.user.uid));
            if (userRef.exists()) {
              const profile = userRef.data();
              setUserProfile(profile);
            }
          }
        }
      } catch (error) {
        console.log("error", error);
      } finally {
        setIsLoading(false);
      }
    };
    userProfile();
  }, [setUserProfile]);
  return {
    isLoading,
    userProfile, setUserProfile
  };
};

export default useGetUserProfile;

So I'm not sure what I'm doing wrong. Where exactly does the context value get set, only in the children? From the context children, do you retrieve the profile data from the hooks and then set it, or do you set the context data in the hooks?

When i try to set the context state variable within the hook I get the error in the pic below: That error is in the actual hook that's getting the user data from the backend. My thought is I updated the context state variable within the hook

发布评论

评论列表(0)

  1. 暂无评论