Search code examples
react-nativereact-hooksreact-context

How to toggle a boolean value using Context and Hooks?


I am using ReactContext and Hooks to show and hide a Modal on click of a button.

Following is my Context code

const setPrivacyPolicyModalVisibility = dispatch => {
  return ({visible}) => {
    visible
      ? dispatch({type: 'enablePrivacyPolicyModalVisibility'})
      : dispatch({type: 'disablePrivacyPolicyModalVisibility'});
  };
};

And the reducer code for the same is something as follows

case 'enablePrivacyPolicyModalVisibility':
      return {...state, ...{enablePrivacyPolicy: true}};
case 'disablePrivacyPolicyModalVisibility':
      return {...state, ...{enablePrivacyPolicy: false}};

Some setup code in my class

const {state, setPrivacyPolicyModalVisibility} = useContext(Context);
  const [privacyVisibility, setPrivacyVisibility] = useState(false);

on click of button I am calling the following code

<TouchableOpacity
        onPress={() => {
          setPrivacyVisibility(true);
          console.log(`${privacyVisibility}`);
          setPrivacyPolicyModalVisibility({privacyVisibility});
        }}.....

As you can see I am console logging the privacyVisibility value but it is always false which I fail to understand

Following is my code in the component to hide or show the Modal

{state.enablePrivacyPolicy ? (
        <SettingsPrivacyModal visible={true} />
      ) : (
        <SettingsPrivacyModal visible={false} />
      )}

The Modal code is proper as I have tried setting default value to true just to check if modal is visible then it works, but on click of button press the state value does not change and I am not able to see the modal as the value is always false


Solution

  • The issue seems to be in the onPress callback:

    onPress={() => {
        const privacyVisibility_new = !privacyVisibility;
    
        console.log( privacyVisibility_new );
    
        setPrivacyVisibility( privacyVisibility_new );
        setPrivacyPolicyModalVisibility( privacyVisibility:privacyVisibility_new );
    }}
    

    When the cycle reaches the callback privacyVisibility has the default which is false. I think you are assuming that once setPrivacyVisibility is called, the privacyVisibility variable will have the new value in that same cycle; but it won't have the updated value until the component renders again.


    setPrivacyPolicyModalVisibility doesn't seem to be correct. I am not sure where is dispatch exactly, but assuming it is at the same level as the function you can simply use it inside.

    const setPrivacyPolicyModalVisibility = visible => {
        if ( visible ) {            
            dispatch({ type: "enablePrivacyPolicyModalVisibility" });
        } else {
            dispatch({ type: "disablePrivacyPolicyModalVisibility" });
        }
    };
    

    You might want to simplify your reducer and send directly the visible value:

    const setPrivacyPolicyModalVisibility = visible =>
        dispatch({ type: "setPrivacyPolicyModalVisibility", payload: visible });
    

    .

    case 'setPrivacyPolicyModalVisibility':
        return { ...state, is_privacyPolicy_visible: action.payload };