简体   繁体   中英

How can I access my react hooks state from inside a function

I have an app that shows some questions when the user presses a button. On each questions I have a condition to determine if the "Back" button should be shown on the question - appState.questions.length > 0 .

My problem is that the state is not being reached from the function where I am calling it.

let questionComponent = (currentCardKey, textAreaText = "") => {
    console.log(`Question length inside: ${appState.questions.length}`)
    return <Question
        textAreaText={"ereer"}
        // I can not access appState from here.
        shouldShowBackButton={appState.questions.length > 0}
        measureTextChangeHandler={measureTextChangeHandler}
        onChosenDataTypeChanged={onChosenDataTypeChanged}
        aimTextChangeHandler={aimTextChangeHandler}
        onButtonClicked={onButtonClicked}
        currentCardKey={currentCardKey}/>
}

The structure of my code.

function App(){
    const [appState, setAppState] = useState(
        {
            questions: [], //[<Question />, <Question />]
            independentVariablesCount: 0,
        }
    )
    const [currentCard, setCurrentCard] = useState();
    
    const addToQuestion = (questionObject) => {
        setAppState(prevState => {
            questionLength.current = appState.questions.length
            return {...prevState, questions: [...prevState.questions, questionObject]}
        })
    }

    // I can access appState outside the function
    
    let questionComponent = (currentCardKey, textAreaText = "") => {

        console.log(`Question length inside: ${appState.questions.length}`)

        return <Question
            textAreaText={"ereer"}
           // I can not access appState inside this function
            shouldShowBackButton={appState.questions.length > 0}
            measureTextChangeHandler={measureTextChangeHandler}
            onChosenDataTypeChanged={onChosenDataTypeChanged}
            aimTextChangeHandler={aimTextChangeHandler}
            onButtonClicked={onButtonClicked}
            currentCardKey={currentCardKey}/>
    }

    const onButtonClicked = (_buttonText, previousCardComponent) => {
        const previousCard = previousCardComponent
        const previousCardMainText = previousCardComponent.props.mainText
        ...
        switch (_buttonText) {
            case buttonText["NEXT"]:
                switch (previousCardMainText){
                    case questionData["CAT_QUESTION"]:
                        addToQuestion(previousCard)
                        setCurrentCard(questionComponent("CAT_FOOD_QUESTION"))
                        break
                }
            ...
                break
        }
    }

    return (
        <div>{currentCard}</div>
    )
}

I have tried updating the function inside useEffect() but that does not solve the problem. I have searched for solutions such as useState function is not working in functional component and React hooks setState not updating immediately but none of these work.

How can this issue be resolved?

Two things I did wrong, I did not remember to add the first question to the state array when the start button is clicked and I did not make a way for the question component to be re-rendered with the correct value when the question length changes. Used the useRef hook to store the questionComponent function.

So I used the useRef hook to store the questionComponent and used the addToQuestion function I had.

const questionComponent = useRef()

useEffect(()=>{
    questionComponent.current = (currentCardKey, textAreaText = "") => {
        console.log(`Question length inside: ${appState.questions.length}`)
        return <Question
            textAreaText={"ereer"}
            shouldShowBackButton={appState.questions.length > 0}
            measureTextChangeHandler={measureTextChangeHandler}
            onChosenDataTypeChanged={onChosenDataTypeChanged}
            aimTextChangeHandler={aimTextChangeHandler}
            onButtonClicked={onButtonClicked}
            currentCardKey={currentCardKey}/>
    }
})

const onStartButtonClick = () => {
    setStartButtonIsClicked(true)
    setCurrentCard(questionComponent.current("CAT_FOOD_QUESTION"))
    addToQuestion(questionComponent.current("CAT_FOOD_QUESTION"))
}

you access to the initial appState due to the javascript clousure feature, so the appState length keeps 0 all the time.

try this:

let questionComponent = React.useMemo((...) => {}, [appState]);

then you can access to the newest appState

Have you tried to use useCallback?

Const questionComponent = useCallback((currentCardKey, textAreaText = "") => {

        console.log(`Question length inside: ${appState.questions.length}`)

        return <Question
            textAreaText={"ereer"}
           // I can not access appState inside this function
            shouldShowBackButton={appState.questions.length > 0}
            measureTextChangeHandler={measureTextChangeHandler}
            onChosenDataTypeChanged={onChosenDataTypeChanged}
            aimTextChangeHandler={aimTextChangeHandler}
            onButtonClicked={onButtonClicked}
            currentCardKey={currentCardKey}/>
    },[appState])

Hope it helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM