[英]React Function Component doesn't update view onClick
我是反應新手。 我有一個我創建的評級組件。 我遇到的問題是 onClick 我可以在控制台中看到評級正在更新,但在頁面上我沒有看到發生的變化。 我的理解是 React 組件需要是純函數,最好是函數式組件而不是類。 當我嘗試使用 useState 掛鈎時,我的評分被添加到之前的 state 並且沒有在頁面上正確更新。
我的第一個問題是在組件中更新 state 的最佳/首選方法是什么? 如果我使用的是功能組件,我必須使用鈎子嗎?
請在下面查看我的代碼
export default function Rating(props) {
let stars = [];
// const [stars, setStars] = useState([]);
let star = '☆';
for (let i = 0; i < props.stars; i++) {
stars.push(star);
}
function rate(index) {
let filledStar = '★'
let stars = [];
// setStars([])
for (let i = 0; i < props.stars; i++) {
stars.push(star);
}
stars.forEach((star, i) => {
while (index >= 0) {
stars[index] = filledStar;
index--;
}
})
console.log('stars filled', stars)
return stars
}
return (
<>
<div className="stars">
{stars.map((star, i) => (
<h2
key={i}
onClick={() => rate(i)}>{star}
</h2>
))}
</div>
</>
)
}
如果我單擊第四顆星,則會按預期返回,但 UI 不會更新。
正如您所建議的,您需要使用掛鈎來尋找您正在尋找的功能(或使用 class 組件)。 在您當前的實現中,您實際上並沒有使用 React 狀態,因此 React 不知道您希望它重新渲染您的組件。 此外,您在 rate() 中使用的 stars 數組與組件中的 stars 數組不同。 您似乎沒有使用由 rate() 創建和返回的 stars 數組
您究竟是如何嘗試使用 useState 的?
這是一個工作版本,它使用useState
和useEffect
填充星號,包括被點擊的星號。
const { Fragment, useEffect, useState } = React; function Rating(props) { // Set state as an empty array const [stars, setStars] = useState([]); // Called by useEffect his function // creates a new array of empty stars function initStars() { const stars = []; for (let i = 0; i < +props.stars; i++) { stars.push('☆'); } setStars(stars); } // Called when the component // first mounts, and called only once useEffect(() => { initStars(); }, []); function rate(e) { // Get the id from the star dataset const { id } = e.target.dataset; // Create a fresh array const stars = []; // Loop; if the current index is less or // equal to the id set it as a filled star // otherwise set it to an empty star for (let i = 0; i < +props.stars; i++) { stars.push(i <= +id? '★': '☆'); } // Set the state with the new array setStars(stars); } return ( <Fragment> <div> {stars.map((star, i) => ( <span className="star" key={i} data-id={i} onClick={rate} >{star} </span> ))} </div> </Fragment> ); }; ReactDOM.render( <Rating stars="10" />, document.getElementById('react') );
.star { font-size: 1.8em; }.star:hover { cursor: pointer; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script> <div id="react"></div>
所以,看來我需要使用 useState 鈎子。 我敢肯定還有另一種方法可以做到這一點,但這對我有用。
export default function Rating(props) {
const [stars, setStars] = useState([]);
let star = '☆';
function initStars() {
const stars = [];
for (let i = 0; i < props.stars; i++) {
stars.push(star);
}
setStars(stars);
}
// Called when the component
// first mounts, and called only once
useEffect(() => {
initStars();
}, []);
function rate(index) {
console.log('index', index);
let filledStar = '★'
let stars = [];
console.log('setStars', stars);
for (let i = 0; i < props.stars; i++) {
stars.push(star);
}
stars.forEach((star, i) => {
while (index >= 0) {
stars[index] = filledStar;
index--;
}
})
console.log('stars filled', stars)
// return stars
setStars(stars)
}
// console.log('stars', stars);
return (
<>
<div className="stars">
{stars.map((star, i) => (
<h2
key={i}
onClick={() => rate(i)}>
{star}
</h2>
))}
</div>
</>
)
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.