Dilhan Bhagat
Dilhan Bhagat

Reputation: 498

React useCallback called before useState issue

When they press submit I am trying to alert the user as to what option they chose based on the CheckBox .

However I am having a problem in which when I check the checkbox of today and tomorrow the actual state outside the handleSubmit function is true however in the handleSubmit function both today and tomorrow are false and I don't know how to get the actual state to render in useCallBack hook. Therefore today and tomorrow in useCallBack will always be false

Please can someone see where I am going wrong and assist me with this hook problem. Thank You!!!

import React, { useEffect, useState, useCallback } from 'react'
import { CheckBox } from 'react-native-elements'
import { Alert } from 'react-native'

const Choose = (props) => {
    const [today, setToday] = useState(false)
    const [tommorow, setTommorow] = useState(false)

    useEffect(() => {
        props.navigation.setParams({ handleSubmit: handleSubmit })
    }, [handleSubmit])

    console.log(`today is ${today}`) // this works and is changed by the check box
    const handleSubmit = useCallback(() => {
        if (today == true){
            console.log(`today is ${today}`) // today from outise this function is never true
            
            Alert.alert('You selected today')
        }else if (tommorow == true){
            Alert.alert('You selected tommorow')
        }
    }, [today, tommorow])

    return (
        <View>
            <CheckBox
                checked={world}
                onPress={() => setToday(!today)}
                title='Today'
            />
            <CheckBox
                onPress={() => setTommorow(!tommorow)}
                title='Tommorow'
            />
        </View>
    )
}
export default ChooseToAdd

Choose.navigationOptions = () => {
    const submit = navigationData.navigation.getParam('handleSubmit')
    return {
        headerRight: () =>
            <TouchableOpacity onPress={submit}>
                <Text>Submit</Text>
            </TouchableOpacity>
    }
}

Upvotes: 0

Views: 585

Answers (2)

James
James

Reputation: 176

I'm curious as to what this does: One of the suggestions I've read elsewhere is to move functions declarations outside of the scope of the component as this makes them constant without needing to use useCallback. I'm thinking this will exhibit the same behavior though...I'm thinking that the setParams / submit handler is going to have a stale closure over state?

    import React, { useEffect, useState, useCallback } from 'react'
    import { CheckBox } from 'react-native-elements'
    import { Alert } from 'react-native'
    
    function handleSubmit(today,tomorrow) {
    return () => {
            if (today == true){
                console.log(`today is ${today}`)             
                Alert.alert('You selected today')
            }else if (tommorow == true){
                Alert.alert('You selected tommorow')
            }
    
    };
        }
    
    const Choose = (props) => {
        const [today, setToday] = useState(false)
        const [tommorow, setTommorow] = useState(false)
    
        props.navigation.setParams({ handleSubmit: handleSubmit(today,tomorrow) });

const handleTodayclicked() => {
setToday(!today);
props.navigation.setParams({ handleSubmit: handleSubmit(today,tomorrow) });
};

const handleTomorrowClicked() => {
setTommorow(!tommorow);
props.navigation.setParams({ handleSubmit: handleSubmit(today,tomorrow) });
}; 
   
        return (
            <View>
                <CheckBox
                    checked={world}
                    onPress={() => handleTodayclicked()}
                    title='Today'
                />
                <CheckBox
                    onPress={() => handleTomorrowClicked()}
                    title='Tommorow'
                />
            </View>
        )
    }
    export default ChooseToAdd
    
    Choose.navigationOptions = () => {
        const submit = navigationData.navigation.getParam('handleSubmit')
        return {
            headerRight: () =>
                <TouchableOpacity onPress={submit}>
                    <Text>Submit</Text>
                </TouchableOpacity>
        }
    }

Upvotes: 0

D10S
D10S

Reputation: 1559

Why not change this

    useEffect(() => {
        props.navigation.setParams({ handleSubmit: handleSubmit })
    }, [handleSubmit])

    console.log(`today is ${today}`) // this works and is changed by the check box
    const handleSubmit = useCallback(() => {
        if (today == true){
            console.log(`today is ${today}`) // today from outise this function is never true
            
            Alert.alert('You selected today')
        }else if (tommorow == true){
            Alert.alert('You selected tommorow')
        }
    }, [today, tommorow])

to this

    useEffect(() => {
        const handleSubmit = () => {
            if (today == true){
                Alert.alert('You selected today')
            }else if (tommorow == true){
                Alert.alert('You selected tommorow')
            }
        }
        props.navigation.setParams({ handleSubmit: handleSubmit })
    },[today, tommorow])

Upvotes: 1

Related Questions