簡體   English   中英

React Function 組件不更新視圖 onClick

[英]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 不會更新

如果我單擊第四顆星,則會按預期返回,但 UI 不會更新。

正如您所建議的,您需要使用掛鈎來尋找您正在尋找的功能(或使用 class 組件)。 在您當前的實現中,您實際上並沒有使用 React 狀態,因此 React 不知道您希望它重新渲染您的組件。 此外,您在 rate() 中使用的 stars 數組與組件中的 stars 數組不同。 您似乎沒有使用由 rate() 創建和返回的 stars 數組

您究竟是如何嘗試使用 useState 的?

這是一個工作版本,它使用useStateuseEffect填充星號,包括被點擊的星號。

 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM