You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unsplash登录成功后背景色不更新,仅刷新页面生效的问题排查

问题解决:登录后图片背景色不自动更新与并发请求处理

核心问题分析

  1. 背景色不自动更新:getUserProfile仅将用户名存入localStorage,但未更新Context中的username状态,导致ImageList中监听username的useEffect无法触发,进而不会调用getLikedPhotos获取点赞列表。此外,Login组件的useEffect逻辑存在异步时序问题,getToken执行完成前就判断token是否存在,导致getUserProfile可能无法正确触发。
  2. 并发请求无序:getToken、getUserProfile、getLikedPhotos三个请求存在依赖关系,但当前代码未保证执行顺序,可能出现请求并发导致数据不一致的情况。

具体修改方案

1. 更新Context中的username状态

在appContext.js的getUserProfile方法中,添加dispatch更新Context的username:

const getUserProfile = async () => {
  try {
    const { data } = await axios.get(`https://api.unsplash.com/me`, {
      headers: {
        "Content-Type": "application/json",
        Authorization: "Bearer " + state.token,
      },
    });
    const { username } = data;
    localStorage.setItem("username", username);
    // 新增:更新Context中的username
    dispatch({
      type: "SET_USERNAME",
      payload: { username },
    });
  } catch (error) {
    console.log(error);
  }
};

同时在reducer.js中添加对应的处理逻辑:

import { SET_TOKEN, SET_LIKED_PHOTOS_ID, SET_USERNAME } from "./actions";

const reducer = (state, action) => {
  if (action.type === SET_TOKEN) {
    return {
      ...state,
      token: action.payload.access_token,
    };
  }

  if (action.type === SET_LIKED_PHOTOS_ID) {
    return {
      ...state,
      likedPhotosId: action.payload.likedPhotosId,
    };
  }

  // 新增:处理用户名更新
  if (action.type === SET_USERNAME) {
    return {
      ...state,
      username: action.payload.username,
    };
  }

  throw new Error(`no such action : ${action.type}`);
};

在actions.js中添加SET_USERNAME常量:

export const SET_TOKEN = "SET_TOKEN";
export const SET_LIKED_PHOTOS_ID = "SET_LIKED_PHOTOS_ID";
export const SET_USERNAME = "SET_USERNAME";

2. 修复Login组件的异步时序问题

将Login中的useEffect改为串行处理异步请求,确保getToken完成后再执行getUserProfile:

import React, { useEffect } from "react"
import { useAppContext } from "../context/appContext";

function Login() {
  const { handleClick, getToken, token, getUserProfile } = useAppContext();

  useEffect(() => {
    const handleLoginFlow = async () => {
      if (window.location.search.includes("code=")) {
        await getToken(); // 等待token获取完成
      }
      if (token) {
        await getUserProfile(); // 等待用户名获取完成
      }
    };
    
    handleLoginFlow();
  }, [token, getToken, getUserProfile]);

  return (
    <div>
      <button onClick={() => handleClick()}>Log in</button>
    </div>
  );
}

export default Login;

3. 串行化依赖请求,避免并发问题

在getUserProfile完成后直接调用getLikedPhotos,确保依赖顺序:

const getUserProfile = async () => {
  try {
    const { data } = await axios.get(`https://api.unsplash.com/me`, {
      headers: {
        "Content-Type": "application/json",
        Authorization: "Bearer " + state.token,
      },
    });
    const { username } = data;
    localStorage.setItem("username", username);
    dispatch({
      type: SET_USERNAME,
      payload: { username },
    });
    // 用户名获取后直接调用getLikedPhotos
    await getLikedPhotos();
  } catch (error) {
    console.log(error);
  }
};

4. 优化ImageList的渲染逻辑

将key属性绑定在最外层元素上,避免React渲染异常:

return (
  <div className="result">
        {images?.map((image) => (
          <div
            key={image.id} // 将key移到最外层div
            style={{
              backgroundColor: likedPhotosId?.includes(image.id) ? "red" : "",
            }}
          >
              <img src={image.urls.small} alt={image.alt_description} />
          </div>
        ))}
  </div>
);

效果验证

  1. 点击登录按钮跳转至Unsplash登录页,登录成功后重定向回本地页面。
  2. 页面会自动依次完成token获取、用户名获取、点赞列表获取流程。
  3. 点赞过的图片背景色会自动变为红色,无需手动刷新页面。
  4. 所有依赖请求串行执行,不会出现并发导致的数据不一致问题。

内容的提问来源于stack exchange,提问作者john

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 22:11:03