Checkbox state isn't changing after click - react-native

I create an app and use react native and ui kitten. The whole thing works with Expo. Now I have implemented a checkbox, but when I tap on the checkbox with the Expo app (iOS), there is no check. The variable is changed, but the state of the checkbox does not change.
<CheckBox
style={style.checkbox}
checked={privacyChecked}
onChange={(checked) => {
privacyChecked = checked;
}}
>
I accept the Privacy's
</CheckBox>
The default value is false. I tap on it and I set the variable to true. But the checkbox isn't changing.

You cannot update the state with = assignment
you need to use setState function like
onChange={(checked) => this.setState(checked)}
because react will not re-render the component unless it patch the changes and know that it needs to do the re-rendering of component

Related

Set state to initial state in react native

I would like to know if it's possible to set the state to the initial state values whenever we press back the button in the tabBar ? At the moment, when I leave the tabBar and come back after a few navigation in the app, the infos that the user enter in TextField persist.
Thanks !
You could use React hooks to achieve similar results to lifecycle methods in class functions.
The useEffect method runs on component render. You can set the state in there.
const [currentState, setCurrentState] = useState(null);
useEffect(()=>{
// This will run after 1st render
setCurrentState("");
},[]);

Why does Switch in ReactNative show toggle animation although its value prop is not changed? (iOS)

I am experiencing some behavior of a ReactNative Switch that I cannot explain.
I have a very simple switch (see code below). It has a fixed value prop and its onValueChange-callback is only a log. As a switch is a controlled component, I thought the UI is only rerendered when the value prop changes.
Despite my assumptions the switch shows a quick animation of toggling to false and then jumps back to true. Why is that happening? Does it have to do with the iOS specific component that is used by ReactNative?
import React from "react";
import { Switch, View } from "react-native";
export const SwitchCell = () => {
return (
<View>
<Switch onValueChange={() => console.log("Test")} value={true} />
</View>
);
};
If you want to block the event there is a prop for switch called "onChange" where as parameter you will receive the event and the new value, you can execute a check to decide if will be necessary to set the new property o if it won't change.
In case you doesn't want to change the value of switch you have to call the methods "preventDefault()"

How to deal with state during a screen transition using react native and react navigation

I am getting an object undefined exception during a transition from one screen to another. I have a pretty good idea what is happening, I am just not sure if there is a clean way of handling it without just checking for undefined everywhere.
Here is my scenario:
Source screen references a user object in a Redux store
Navigation is initiated from the source screen to the destination screen.
The destination screen componentDidMount() is called where I clear the user object from the Redux store.
The source screen render() gets called again and the undefined error occurs because I cleared user from the store.
I am assuming that the source and destination screens have some overlap due to the transition. I have tried adding listeners with no luck. I can only get listener handlers to fire for type = action,
I am probably making this more complicated than it is, but I would like to find out if there is a standard way of dealing with this or if I am going about it in a completely wrong way.
Also, my react-navigation is integrated with Redux as per the instructions on React Navigation's website and the Redux React Navigation sample code.
Here is the basic code.
Screen 1
componentDidMount() {
// This is a Redux action that sets an object called user to null
clearUser();
{
Screen 2
render() {
return (
// Other code here
// user is null here because render gets called after Screen1#componentDidMount() gets called
<Text>{user.firstName + ' ' + user.lastName}</Text>
<TouchableOpacity
onPress={() => navigation.dispatch({ type:'NAV_SCREEN_1' })}
>
// button code here
</TouchableOpacity>
// Other code here
)
}
The type of error is "TypeError: Cannot read property 'firstName' of null"
I understand the error and why I am getting it. The user object has been set to null by my Redux action in componentDidMount() of Screen 1 and then Redux causes render of Screen 2 to get called which is referencing a user object which is null.
My question is, is there a special way to accommodate this behavior without having to check if the user object is null every place I need to use it ? Should I call clearUser() somewhere else ?
For the newest version of react-navigation, you can use either addListener, withNavigationFocus or isFocused to detect transition state of the screens.
Another unofficial way is to catch action type NavigationActions.COMPLETE_TRANSITION, in case of using middleware like redux-saga.
As an alternative, you can simply make your Redux-connected screen handle undefined or null state. I had a similar problem and I ended up rendering a loader instead of the screen content when user state is undefined. When I log out, the screen shows a loader for a fraction of a second, then the app navigates away.

How to re-render part of the component upon state change?

I have a component the includes progress.circle from the library react-native-progress (see link: https://github.com/oblador/react-native-progress).
Initially I set the progress prop of the progress circle to a state variable that is set to 0 at idle state as shown in the code below:
<Progress.Circle
showsText={true}
progress={this.state.progress} // this.state.progress = 0
size={width * 0.1388888888888}
color={"#EF5D6C"}
/>
Number of user interactions take place to set the state variable (this.state.progress) to a certain percentage then the component re-render to show the progress animation as intended.
Problem is the component flashes for part of a second as result of the re-rendering process.
So is there a way to only re-render the progress circle and leave the rest of the component in its current rendering form.
You could try separating out the Progress.Circle element into a different file so its in its own renderer.
render() {
return (
<Progress.Circle
showsText={true}
progress={this.state.progress} // this.state.progress = 0
size={width * 0.1388888888888}
color={"#EF5D6C"}
/>
)
}
That way when you change the element in state only the progress.circle should re-render. Then you would import this into your main file and call it there:
render(){
....
<ProgressCircle />
....
}
Basically whatever is inside the render function will re-render. If the progress.circle element is on its own where the state is changed, only it should re-render as far as i know.
Hope this helps in some way!
Make the progress.circle view as a separate component, as suggested in the previous answer. Keep the progress value in global state, which can be accessed by this separate component. If you are using Redux, you can do this easily. Then pass that state.progress value in the progress prop of the Progress.Circle

React Native Flip Card default clickable false and make true on button click

I am working on React Native Project, I am using react-native-flip-card this component.
My requirement is to make clickable false on initial start and on click of button make clickable true for the flip cards.
In the case you want to modify a behaviour inside a Component, the State Component seems like the things you need.
You can set a state property such as :
this.state = {
isClickable: false,
}
by default in your Component Constructor.
And then assign this value to your FlipCard component, such as :
<FlipCard
*Your other properties*
clickable={this.state.isClickable}
>
Finally, just update your state property when another event such as a button click happens :
<Button
onPress={() => this.setState({isClickable: true})}
title="Make Flipcard clickable"
color="#841584"
/>
That's it ! Do not hesitate to ask more question if something isn't clear enough.