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

React中useStarRating钩子点击星星后currentValue始终返回0

React自定义useStarRating钩子状态同步问题解决

问题核心

你的代码存在状态完全脱节的问题:

  • Star组件自己维护了独立的currentValue和hoverValue状态,完全没有使用useStarRating钩子的状态;
  • AddReviews组件读取的是钩子的状态,两者完全无关,导致父组件永远拿不到Star组件点击后的评分值;
  • 钩子中currentValue初始值为undefined,与Star组件的初始0值不匹配,也会导致显示异常。

解决方案

1. 改造Star组件为受控组件

移除Star组件内部的状态,改为接收外部传入的状态和操作方法:

// Star.js
import { faStar } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';

const Star = ({ currentValue, hoverValue, handleStarClick, handleStarHover, handleStarLeave }) => {
  const stars = Array(5).fill(0);

  return (
    <div>
      <div className="cursor-pointer my-3">
        {stars.map((_, index) => {
          return (
            <FontAwesomeIcon
              key={index}
              icon={faStar}
              size="xl"
              color={(hoverValue || currentValue) > index ? '#FFD700' : '#A9A9A9'}
              onClick={() => handleStarClick(index + 1)}
              onMouseOver={() => handleStarHover(index + 1)}
              onMouseLeave={handleStarLeave}
            />
          );
        })}
      </div>
    </div>
  );
};

export default Star;

2. 调整AddReviews组件,传递钩子状态给Star

将useStarRating返回的状态和方法全部传递给Star组件:

// AddReviews.js
import Star from './Star';
import useStarRating from '@/hooks/useStarRating';
import axios from 'axios';
import { useState } from 'react';

const AddReviews = () => {
  const { currentValue, hoverValue, handleStarClick, handleStarHover, handleStarLeave } = useStarRating();
  const [reviewText, setReviewText] = useState('');

  const handleReviewTextChange = (event) => {
    setReviewText(event.target.value);
  };

  console.log('currentValue:', currentValue);

  const handleSubmit = (event) => {
    event.preventDefault();

    axios
      .post('http://localhost:8080/review/2/user', {
        rating: currentValue,
        reviewText: reviewText,
      })
      .then((response) => console.log(response.data))
      .catch((error) => console.error(error));
  };

  return (
    <div>
      <p className="text-xl">Add Review</p>
      <div>
        <form className="flex flex-col" onSubmit={handleSubmit}>
          <Star 
            currentValue={currentValue}
            hoverValue={hoverValue}
            handleStarClick={handleStarClick}
            handleStarHover={handleStarHover}
            handleStarLeave={handleStarLeave}
          />
          <textarea
            className="border border-gray-400 rounded-lg p-2"
            value={reviewText}
            onChange={handleReviewTextChange}
          ></textarea>
          <button className="bg-blue-500 text-white font-bold py-2 px-2 rounded-lg mt-2 ">
            Post Review
          </button>
        </form>
      </div>
    </div>
  );
};

export default AddReviews;

3. 修正useStarRating钩子的初始值和职责

移除不必要的UI导入,将currentValue初始值设为0,保持与显示逻辑一致:

// useStarRating.js
import { useState } from 'react';

const useStarRating = () => {
  const [currentValue, setCurrentValue] = useState(0);
  const [hoverValue, setHoverValue] = useState(undefined);

  const handleStarClick = (value) => {
    setCurrentValue(value);
    // 注意:setState是异步操作,此处直接打印currentValue会拿到旧值,验证请在组件渲染阶段打印
  };

  const handleStarHover = (value) => {
    setHoverValue(value);
  };

  const handleStarLeave = () => {
    setHoverValue(undefined);
  };

  return {
    currentValue,
    hoverValue,
    handleStarClick,
    handleStarHover,
    handleStarLeave,
  };
};

export default useStarRating;

关键说明

  • 受控组件模式:Star组件不再维护内部状态,所有状态由外部钩子控制,确保父组件与子组件状态完全同步;
  • 钩子职责单一:钩子只负责状态管理,移除不必要的UI组件导入,符合自定义钩子的设计原则;
  • 异步状态更新:useState的更新是异步的,所以在handleStarClick中直接打印currentValue会拿到旧值,这是React的正常行为,验证状态请在组件渲染阶段(如AddReviews中的console.log)查看。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 15:25:03