useStarRating()钩子即使在与星型组件交互后也返回0



我正在使用一个自定义的useStarRating钩子来管理我的React项目中的星级评级组件的状态。钩子似乎工作得很好,但是在用户与星形组件交互后,我在获取currentValue的最新值时遇到了麻烦。

即使在单击星号之后,父组件中的currentValue也总是返回0。我试过记录父组件和Star组件中currentValue的值,但它总是显示0。

下面是我的AddReviews组件的代码:

// AddReviews.js
import Star from './Star';
import useStarRating from '@/hooks/useStarRating';
import axios from 'axios';
import { useState } from 'react';
const AddReviews = () => {
const { currentValue } = 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 />
<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;

下面是我的Star组件的代码:

// Star.js
import { faStar } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { useState } from 'react';
const Star = () => {
const stars = Array(5).fill(0);
const [currentValue, setCurrentValue] = useState(0);
const [hoverValue, setHoverValue] = useState();
const handleClick = (value) => {
setCurrentValue(value);
};
const handelMouseHover = (value) => {
setHoverValue(value);
};
const handelMouseLeave = () => {
setHoverValue(undefined);
};
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={() => handleClick(index + 1)}
onMouseOver={() => handelMouseHover(index + 1)}
onMouseLeave={handelMouseLeave}
/>
);
})}
</div>
</div>
);
};
export default Star;

这里是我的钩子useStarRating的代码

import { faStar } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { useState } from 'react';
const useStarRating = () => {
const [currentValue, setCurrentValue] = useState(undefined);
const [hoverValue, setHoverValue] = useState(undefined);
const handleStarClick = (value) => {
setCurrentValue(value);
console.log("value");
console.log(currentValue);
};
const handleStarHover = (value) => {
setHoverValue(value);
};
const handleStarLeave = () => {
setHoverValue(undefined);
};
return {
currentValue,
hoverValue,
handleStarClick,
handleStarHover,
handleStarLeave,
};
};
export default useStarRating;

这里的主要问题是你的钩子没有/are全局状态。

AddReviews组件中的钩子是useStarRating的一个新实例。这将为hoverValuecurrentValue创建一个新状态。

解决这个问题的一种方法是将所需的值和函数与props一起传递下去。您的Star组件看起来像这样:

const Star = ({ hoverValue, currentValue, setCurrentValue, setHoverValue }) => {
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={() => setCurrentValue(index + 1)}
onMouseOver={() => setHoverValue(index + 1)}
onMouseLeave={() => setHoverValue(undefined)}
/>
);
})}
</div>
</div>
);
};

现在在您的AddReviews组件中,您可以传递所需的值。

const AddReviews = () => {
const { currentValue, setCurrentValue, hoverValue, setHoverValue } =
useStarRating();
const [reviewText, setReviewText] = useState("");
// ...
return (
// ...
<Star
currentValue={currentValue}
setCurrentValue={setCurrentValue}
hoverValue={hoverValue}
setHoverValue={setHoverValue}
/>
// ...
);
};

另一种解决方法是使用React context。

const StarRatingContext = createContext({});
function StarRatingProvider({ children }) {
const [currentValue, setCurrentValue] = useState(undefined);
const [hoverValue, setHoverValue] = useState(undefined);
const handleStarClick = (value) => {
setCurrentValue(value);
console.log("value");
console.log(currentValue);
};
const handleStarHover = (value) => {
setHoverValue(value);
};
const handleStarLeave = () => {
setHoverValue(undefined);
};
return {
currentValue,
hoverValue,
handleStarClick,
handleStarHover,
handleStarLeave,
};
return <StarRatingContext.Provider>{children}</StarRatingContext.Provider>;
}
const useStarRating = () => useContext(StarRatingContext);

将您的AddReviews组件包装在StarRatingProvider中,您将在两个组件中拥有您的数据。