Node.js 在react和nodejs中实时更新

Node.js 在react和nodejs中实时更新,node.js,reactjs,next.js,Node.js,Reactjs,Next.js,我试图实现当用户上传他们的个人资料图片到网站上,它会自动将旧的个人资料图片更改为新的个人资料图片,而不是用户必须注销并重新登录,使其工作 以下是我的前端代码库: const UserCard = ({ picture, name, userEmail, isVerified, id, setPicture, setUser}) => { const [imageSelected, setImageSelected] = useState("");

我试图实现当用户上传他们的个人资料图片到网站上,它会自动将旧的个人资料图片更改为新的个人资料图片,而不是用户必须注销并重新登录,使其工作

以下是我的前端代码库:

const UserCard = ({ picture, name, userEmail, isVerified, id, setPicture, setUser}) => {

      const [imageSelected, setImageSelected] = useState("");
    
      useEffect(() => {
        if (imageSelected !== '') {
          uploadImage();
        }
         
      }, [imageSelected]);
    
    
      const uploadImage = () => {
        const formData = new FormData();
        formData.append("file", imageSelected);
        formData.append("id", id);
    
        axios
          .post("/api/v1/users/upload/image", formData, {
            headers: { "Content-Type": "multipart/form-data" },
          })
          .then((response) => {
            setPicture(response.data.data.imageUrl);
            setUser(prev => ({ ...prev, picture: response.data.data.imageUrl }));

          });
      };
      // End of Method
      const inputFile = useRef(null);
      const onButtonClick = () => {
        // `current` points to the mounted file input element
       inputFile.current.click();
      };
    
      return (
        <div className="avatar--icon_profile">
          <Card className="profile--card_container">
            <CardContent>
              {picture ? (
                <div>
                  <input
                    className="my_file"
                    type="file"
                    ref={inputFile}
                    onChange={(e) => setImageSelected(e.target.files[0])}
                  />
                    <div className="profile-image">                
                      <Avatar
                          src={picture}
                          alt="Avatar"
                          className="avatar--profile_image"
                          onClick={onButtonClick}
                      />
                      </div>
                 </div>
             </div>
我怎样才能做到呢

添加了GlobalState.js:

const GlobalState = (props) => {
  // User State -----------------------------------------------------------------------------
  const [currentUser, setUser] = useState(props.serverUserData);

  // This method is passed through context to update currentUser
  const updateUser = (userData) => {
    setUser(userData);
  };

  // Modal State -----------------------------------------------------------------------------
  const [isModalOpen, setModalOpenState] = useState(false);
  const [modalToDisplay, setModalToDisplay] = useState("signup");

  // This function will be provided to any function that needs to toggle the modal.
  const toggleModal = () => {
    // Take the previous state and flip it.
    setModalOpenState((prevState) => !prevState);
  };

  // This method is passed through context to update the next modal to open.
  const setModal = (name) => {
    // Take the passed in modal name and set state.
    setModalToDisplay(name);
  };

  // Loading State ---------------------------------------------------------------------------
  // NOT REACT STATE
  const [loading, setLoadingState] = useState(false);

  // This state will be used as messages in effects to refetch data.
  const [reloadThisData, setWhatToReload] = useState("");

  // User profile id for query ----------------------------------------------------------------
  const [userProfileId, setUserProfileId] = useState("");

  // Flag to determine if the header should change css style.  ----------------------------------------------------------------
  const [adjustBrightness, setAdjustBrightness] = useState(false);

  // This is the object passed to GlobalContext.Provider
  const providerValues = {
    isModalOpen,
    toggleModal,
    modalToDisplay,
    setModal,
    currentUser,
    updateUser,
    loading,
    setLoadingState,
    reloadThisData,
    setWhatToReload,
    userProfileId,
    setUserProfileId,
    adjustBrightness,
    setAdjustBrightness,
  };
  
  return (
    <GlobalContext.Provider value={providerValues}>
      {props.children}
    </GlobalContext.Provider>
  );
};

export default GlobalState;
编辑后更新我的代码:

const UserProfile = () => {
  const appState = useContext(GlobalContext);
  const { currentUser, setUser } = appState;
  const { email, name, id } = currentUser;
  const [isVerified, setIsVerified] = useState(false);

  const [picture, setPicture] = useState(currentUser.picture);

  const checkVerificationData = () => {
    axios.get("/api/v1/profiles/profile").then((res) => {
      const { data } = res;   
      if (data.verifiedDT) {
        setIsVerified(data.verifiedDT);
      }
    });
  };

  useEffect(() => {
    checkVerificationData();
  }, [isVerified]);


  const classes = useStyles();
  return (
    <div className={classes.root}>
      <Grid item xs={12}
        container
        direction="row"
        justify="center"
        alignItems="center"
        spacing={4}>
        <Grid item>
          <Grid item>
            <UserCard
              picture={picture}
              setPicture={setPicture}
              userEmail={email}
              name={name}
              isVerified={isVerified}
              id={id}
              setUser={setUser}
            />
            <br />
          </Grid>
          <div>
            <Grid item>
              <div className="profile--layout_userInfo">
                <Grid item>
                  <UserInfo />
                </Grid>
              </div>
            </Grid>
          </div>
        </Grid>
        <div>
          <Grid item>
            <div className="profile--layout_ratings_reviews_block">
              <UserRatingsDetailed userEmail={email} />
            </div>
          </Grid>
        </div>
      </Grid>
    </div>
  );
};

export async function getServerSideProps(context) {
  let serverUserData = {};

  if (
    context.req.session.passport !== undefined &&
    context.req.session.passport.user !== undefined
  ) {
    const userPassportInfo = context.req.session.passport.user;
    const { id, name, email, publicId, picture } = userPassportInfo;
    const isSessionValid = context.req.isAuthenticated();

    serverUserData = {
      id,
      name,
      email,
      publicId,
      picture,
      isSessionValid,
    };
  }

  return { props: { serverUserData } };
}


UserProfile.propTypes = {
  serverUserData: PropTypes.object, 
};

export default UserProfile;
constuserprofile=()=>{
const appState=useContext(GlobalContext);
const{currentUser,setUser}=appState;
const{email,name,id}=currentUser;
const[isVerified,setIsVerified]=使用状态(false);
const[picture,setPicture]=useState(currentUser.picture);
常量checkVerificationData=()=>{
get(“/api/v1/profiles/profile”)。然后((res)=>{
常数{data}=res;
if(数据验证数据){
setIsVerified(data.verifiedDT);
}
});
};
useffect(()=>{
checkVerificationData();
},[isVerified]);
const classes=useStyles();
返回(

); }; 导出异步函数getServerSideProps(上下文){ 让serverUserData={}; 如果( context.req.session.passport!==未定义&& context.req.session.passport.user!==未定义 ) { const userPassportInfo=context.req.session.passport.user; const{id,name,email,publicId,picture}=userPassportInfo; const isSessionValid=context.req.isAuthenticated(); serverUserData={ 身份证件 名称 电子邮件, publicId, 图片, 是有效的, }; } 返回{props:{serverUserData}}; } UserProfile.propTypes={ serverUserData:PropTypes.object, }; 导出默认用户配置文件;
我从回答表单中的评论中得到的建议是,在react应用程序的全局上下文中创建一个类似于其他经理的经理

const GlobalState = (props) => {
    // Profile Image -----------------------------------------------------------------------
    const [currentProfileImage, setProfileImage] = useState(/*props.serverUserData.profileImage??*/);
    ...
};

export default GlobalState;
不要忘记更新您的
providerValues
以包含这些新值

然后,在使用概要文件映像URI的任何位置,都可以使用上下文提供程序中的
currentProfileImage
变量

最后,当您将映像上载到服务器并在响应中接收新URI时,请使用来自全局状态的
setProfileImage
函数更新全局状态下的概要文件映像

const uploadImage = () => {
    const formData = new FormData();
    formData.append("file", imageSelected);
    formData.append("id", id);

    axios.post("/api/v1/users/upload/image", formData, {
        headers: {"Content-Type": "multipart/form-data"},
    }).then((response) => {
        GlobalState.setProfileImage(response.data.data.imageUrl);
    });
};
*我对您的程序没有完整的了解,因此这是我对实现您期望行为的合理方式的最佳猜测


您需要更新
useState
指令的初始状态,以反映profileImage URI在
props
结构中的实际位置,您需要更新
GlobalState
占位符,以反映您实际访问所提供上下文的方式。

您提到注销和登录是显示新配置文件图片的方式,而不是简单的页面刷新。这是因为您在登录过程中对配置文件图片信息进行了初始拉取吗?@HenryEcker我不明白您所说的初始拉取是什么意思?我想我的问题是:您通常如何检索用户的配置文件图片?在你的
uploadImage
函数的末尾,这样做不是一个选项吗?我通过上下文检索用户的信息。我在帖子中添加了我的上下文,然后我的建议是在全局上下文管理中添加类似于
getUserProfileImage
的内容,并在上传新图像后调用它。或者,由于您似乎正在返回照片的新url,请添加一个
updateUserProfileLink
并将新url传递给该url。我刚刚在帖子中添加了console.log currentUser对象。这就是我需要放在useState中的对象吗?
props.serverUserData.picture
currentUser.picture
您只是想更新图片URI。有了关于当前用户结构的新信息,您可能只需使用现有的用户挂钩,并使用
currentUser.picture
setUser(prev=>({…prev,picture:response.data.data.imageUrl}))
。我也不知道在
UserProfile
UserCard
级别创建新挂钩是否有效。我认为您需要直接从上下文访问它们,比如
appState.setUser({…}
appState.currentUser.picture
当前,您似乎只是保留了一个本地副本,而不是直接使用上下文值。
const GlobalState = (props) => {
    // Profile Image -----------------------------------------------------------------------
    const [currentProfileImage, setProfileImage] = useState(/*props.serverUserData.profileImage??*/);
    ...
};

export default GlobalState;
const uploadImage = () => {
    const formData = new FormData();
    formData.append("file", imageSelected);
    formData.append("id", id);

    axios.post("/api/v1/users/upload/image", formData, {
        headers: {"Content-Type": "multipart/form-data"},
    }).then((response) => {
        GlobalState.setProfileImage(response.data.data.imageUrl);
    });
};