0

I'm using React functional component and initialising the state value based on the prop value. But the main problem is that after the re rendering state is not updating the value based on prop it is giving me the old value after the re render.

I have two components 1st is Question component(Parent Component) and 2nd is Bookmark component (Child Component).

In Question component I'm getting the data and passing that data in State.

Timer Component Changes the value of currentQuestion state after every 30 Seconds.

Timer component is working fine that is why I haven't included the code here

And I'm Rendering Bookmark Component the Question ID and isBookmarked prop to default false value

PROBLEM EXPLANATION

Bookmark toggling is working fine.

But when 30 Seconds end Bookmark should be reset to its prop value and that is not happening. I'm getting the old state value after the questions ends. I'have checked that i'm getting the new value in props but state is not working properly in Bookmark Component.

Question.jsx (Parent Component)

function Question({ t, data, timerSeconds }) {
    const [questions, setQuestions] = useState(data);
    const [currentQuestion, setCurrentQuestion] = useState(0);
    const child = useRef(null);

    setTimeout(() => {
        setQuestions(data);
    }, 500)

    const setNextQuestion = () => {
        const nextQuestion = currentQuestion + 1;
        if (nextQuestion < questions.length) {
            setCurrentQuestion(nextQuestion);
            child.current.resetTimer();
        }
    }

    const onTimerExpire = () => {
        setNextQuestion();
    }
    return (
        <React.Fragment>
            <div className="inner__headerdash">
                <div className="leveldata">
                    <h6 className="inner-level__data">{t('level')} : {questions[currentQuestion].level}</h6>
                </div>
                <Timer ref={child} timerSeconds=30 onTimerExpire={onTimerExpire} />
                <div className="total__out__leveldata">
                    <span className="inner__total-leveldata">{currentQuestion + 1} | {questions.length}</span>
                </div>
            </div>
            <div className="text-white bookmark_area" >
                <Bookmark id={questions[currentQuestion].id} isBookmarked={false} />
            </div>

        </React.Fragment>
    )
}

export default Question;

Bookmark.jsx (Child Component)

function Bookmark({ id, isBookmarked, onClick }) {
    const [bookmark, setBookmark] = useState(isBookmarked);
    
    const handleClick = (question_id) => {
        var toggleBookmarkState = !bookmark;
        setBookmark(toggleBookmarkState);
        onClick(question_id, toggleBookmarkState);
    }

    return (
        <button className="btn bookmark_btn" onClick={() => handleClick(id)}>{bookmark ? <FaBookmark className='fa-2x' /> : <FaRegBookmark className='fa-2x' />}</button>
    );
}

export default Bookmark;
Sagar Gor
  • 111
  • 3
  • 13

1 Answers1

1

Setting useState's initial value is a one-time action (like initializing states in a class constructor) and it won't update itself.

You can make use of a useEffect hook to update it in the Bookmark component.

useEffect(() => setBookmark(isBookmarked), [id]);

Jalal
  • 334
  • 1
  • 4
  • 16