TouchableOpacity onPress not working(emulator test) - reactjs

So just getting started with react-native. I have a stateful component built as below :
class LoginView extends Component {
constructor(props) {
super(props);
this.state = {
inProgress: false
};
}
processLogin(){
this.setState({
inProgress: true
})
}
render() {
return (
<View style={styles.mainContainer}>
<View style={styles.loginContainer}>
<TextInput style={styles.input} placeholder="Password" />
<TouchableOpacity style={styles.button} onPress={() => this.processLogin()}>
{!this.state.inProgress && <Text style={styles.button_text}>Log in</Text>}/>}
</TouchableOpacity>
</View>
</View>
);}}
As you can see, i am binding the onPress event of the touchable opacity to the function processLogin. But for some reason, the function isn't fired!
The state doesn't change, also tried console.log but didn't fire either. Made sure that TouchableOpacity is imported from React-Native.
I am guessing that i messed up the binding. Any leads would be appreciated!
Note: Have only been trying this in the emulator, not in a real device yet.

instead of using the arrow function on onPress prop, use it when you are declaring the business function processLogin
So concretly, replace the declaration of this method by :
processLogin = () => {
this.setState({
inProgress : true
})
}
Then on onPress method, just change make it like this :
onPress = {this.processLogin}
Contrarily, you refer to the wrong this
Hope it's gonna help you sir
Regards.

Related

React change class attributes

I'm trying to change class attribute in a function, I have a button and I want to change the text as soon as the user clicks it.
I wrote a class and everything but when the user clicks the button nothing happens!
I console logged to see if the variables actually changed and they did so why does it happen?
Here is my code:
class App extends Component {
constructor(props) {
super(props);
this.state = {
loading: false,
buttonStatus: 'Post room',
value: '',
}
}
PostANewRoomScreen = () => {
let {data} = '';
return (
<View style={{padding: 15}}>
<TouchableOpacity
style={styles.button}
disabled={this.state.loading}
onPress={() => this.postroom(data)}
>
<Text style={{color: "white" , fontSize: hp('2.5%'), padding: 5}}>
{this.state.loading && <Animated.Image style={{height: hp('3%'), width: wp('2%')}} source={{uri: 'https://media0.giphy.com/media/JTVkOqJ1RyYEBnyoRb/giphy.gif'}} />}
{this.state.buttonStatus}
</Text>
</TouchableOpacity>
</View>
postroom = (value) => {
this.state.loading = true;
this.state.buttonStatus = "button clicked!";
}
this.state.loading = true;
this.state.buttonStatus = "button clicked!";
This does not re render component. You have to use useState Hook (in funcation component) or setState() (in class component) in order to update the state. I suggest converting component to functional component and use hooks to manage state.
const [buttonStatus, setButtonStatus] = useState('Post Room');
then use setButtonStatus(value) inside your postroom function.
Please refer react doc for useSate Hooks
Further, Your existing code has some issues. you are trying to access and mutate state of App component. if you need to share the component state try to lift the state up. If you need to pass properties to component use props.

Synthetic event error when trying to type in textinput

I am building a login page in react-native. Whenever, I type something in the username field, I get a warning: The synthetic event is reused for performance reasons and the value of Text tag is not changed as desired. The code I have written is as below:
export default class LoginScreen extends React.Component {
constructor(props) {
super(props);
this.state = {
username: '',
password: ''
}
}
login = async () => {
// const result = await appLogin(this.state.userName, this.state.password);
console.log(`${this.state.username} ${this.state.password}`);
};
render() {
return <View style={loginStyles.container}>
<ImageBackground
source={require('../../../assets/images/login.jpg')}
style={loginStyles.backgroundImage}>
<View style={loginStyles.titleContainer}>
<Text style={{fontSize: 40, color: 'grey', paddingVertical: 40}}>{this.state.username}</Text>
</View>
<View style={loginStyles.nestedContainer}>
<TextInput
placeholder={'username / email'}
style={[style.inputStyle, style.colorBlue]}
onChange={(username) => this.setState(username)}
/>
<TextInput
placeholder={'password'}
textContentType="password"
secureTextEntry={true}
autoCapitalize="none"
autoCorrect={false}
style={[style.inputStyle, style.colorBlue]}
onChange={(password) => this.setState(password)}
/>
<CustomRoundedButton
text={'Login'}
buttonStyle={[style.bgPrimary]}
onPress={this.login}
textStyle={[style.text20, {color: 'white'}]}
/>
</View>
</ImageBackground>
</View>
}
};
Here is a screenshot to this warning.
Please help me find the solution to this problem.
Replace
onChange={(username) => this.setState(username)}
with
onChangeText={(username) => this.setState({ username })}
and
onChange={(password) => this.setState(password)}
with
onChangeText={(password) => this.setState({ password })}
Hope this helps!
Your code:
onChange={(username) => this.setState(username)}
You should change for this:
onChangeText={(username) => this.setState({ username })}
TextInput's onChange handler is passed a native event object, which you named username in the anonymous function. React state updates are asynchronous, so by the time react is updating state, the event is long gone (been placed back in the event pool).
Use onChangeText instead, it receives the updated input text value.
onChangeText={(username) => this.setState(username)}
Update all your input change callbacks to use onChangeText.

React Native: Invariant Violation: Text strings must be rendered within a <Text> component

Alright, so I'm a bit new to react, and I've made a sample login screen like so:
export default class App extends Component{
constructor(props){
super(props);
this.state = {
login: '',
password: '',
// exists: false,
Button: './submitButton.png',
}
}
render() {
return (
<View>
//Login form here
<View style={styles.container}>
<TextInput
styles = {styles.container}
placeholder = "Login"
onChangeText = {(login) => this.setState({login})}
/>
<TextInput
styles = {styles.container}
placeholder = "Password"
onChangeText = {(password) => this.setState({password})}
/>
</View>
//Button here
<View style={styles.container}>
<TouchableHighlight
onPress = {() => Alert.alert("Alert!")}
>
<Image
style={styles.button}
source={require('./submitButton.png')}
/>
</TouchableHighlight>
</View>
</View>
);
}
}
But I get the error below:
Originally I had used a Button instead of TouchableHighlight because as I understand it, react-native 0.56 (the version I'm using) has a bug regarding buttons, and apparently gives the same issue as above, and the workaround was supposedly to use a TouchableHighlight or TouchableOpacity. But switching to a TouchableOpacity didn't really seem to fix anything.
What do? I've scoured google but I can't seem to find a solution.
(If there's no hope, is there a way to downgrade my installation of react without breaking nearly everything?)
In JSX, comment like //Login form here doesn't work. It will be treated as a text.
You have to change your comments into the shape like below
{/* Login form here */}

React Native Execute a Function on State Change

I am wanting to fire a function when state changes in my app. I have a modal with a button that changes state.
My home component (edited)
...
constructor(props) {
super(props);
this.state = {
color:'red',
modalVisible: false,
}
}
...
render() {
return (
<View>
<Modal
animationType={"slide"}
transparent={false}
visible={this.state.modalVisible}
>
<View style={{marginTop: 22}}>
<TouchableOpacity onPress={()=>this.setState({color:'blue'})}>
<Text>Blue</Text>
<TouchableOpacity>
<TouchableOpacity onPress={()=>this.setModalVisible(false)}>
<Text>Blue</Text>
<TouchableOpacity>
</View>
</Modal>
<Text style={{color:this.state.color}}>
Foo
</Text>
</View>
)
...
However when I close the modal, the color of my text is not changed to blue. It stays red until I open the modal back up, and then close again. Its like the state of 'color' is not being updated. I have ran into this before using redux and 'componentWillReceiveProps(nextProps)' but this has stumped me being in the same component.
I am using the native modal component from the docs. https://facebook.github.io/react-native/docs/modal.html
Touchable? TouchableHighlight?
I have not found any problem in your code except TouchaleHighlight tag.
https://rnplay.org/apps/fDGs3A

props data is not working in componentDidMount using react-native

I have been struggling for the last 24 hrs about this one.
The problem is that, I am passing props in my parent class and calling the props data in my child component. When I check in render method the data shows correctly, but when calling it in componentDidMount it shows null.
Here is the sample of my code
class parent extends React.Component{
constructor(props){
super(props);
this.state = {
isOpen: false,
day:'monday',
data:[],
data1:[]
}
}
back () {
this.props.navigator.pop();
}
Mon(){
var record=[];
this.state.data.map((data) => {
if(data.frequency[0].day == 'Monday'){
record.push(data);
}
});
this.setState({data1:record});
}
componentWillMount() {
this.fetchData();
}
fetchData() {
//here i am getting the data from service and set the data to the state
}
render(){
return(
<View style={styles.Maincontainer}>
<View style={styles.navbar}>
<View style={styles.navbarContainer}>
<View style={styles.navbarIcon}>
<TouchableOpacity style={styles.button} onPress={() => this.back()}>
<Image
style={styles.menu2}
source={require('image!nav_arrow')} />
<Text style={styles.navbuttonText}>Back</Text>
</TouchableOpacity>
</View>
<View style={styles.navbarText}>
<Text style={styles.title}>Title</Text>
</View>
<View style={styles.navbarButton}>
</View>
</View>
</View>
<View style={styles.subMainContainer}>
<View style={styles.weekHeader}>
<View style={styles.weekRow}>
<Text style={styles.text} onPress={this.Mon.bind(this)}>Mon</Text>
</View>
</View>
<View style={styles.listBody}>
{this.state.data1.length == 0 ?(
<List data={this.state.data} />
) : (
<List data={this.state.data1}/>
)}
</View>
</View>
</View>
);
}
}
In my child component, I want to display the data in a ListView which is taken from the parent component
class List extends React.Component{
constructor(props){
super(props);
this.state = {
dataSource: new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2
}),
isLoading: true
};
}
componentDidMount(){ //**here props data shows empty**
alert("didMount:"+JSON.stringify(this.props.data));
var data=this.props.data
this.setState({
dataSource: this.state.dataSource.cloneWithRows(data),
isLoading: false
});
}
render() { //**In this alert it shows correct data**
alert("data:"+JSON.stringify(this.props.data));
if (this.state.isLoading) {
return this.renderLoadingView();
}
return(
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderSchedule.bind(this)}
automaticallyAdjustContentInsets={false}/>
);
}
renderLoadingView(){
return(
<View style={styles.loading}>
<ActivityIndicatorIOS
size='large'/>
<Text>
Loading Schedule...
</Text>
</View>
);
}
renderSchedule(data){
return(
<View style={styles.ListContainer}>
<View style={styles.subContainer}>
<Text style={styles.classText}>Class Name: {data.name}</Text>
{data.frequency[0].day == null ? (
<Text style={styles.Day}>Day: {data.frequency[0].date}</Text>
):
<Text style={styles.Day}>Day: {data.frequency[0].day}</Text>
}
</View>
<View style={styles.subContainer1}>
<Text style={styles.startTime}>Start: {data.frequency[0].from}</Text>
<Text style={styles.endTime}>End: {data.frequency[0].to}</Text>
</View>
</View>
)
}
}
Here what i want is that initially i need to display the total data,when click on the text parent class the data need to be changed.I want to show the data in ListView.I already explain above about my problem,So can any one give me suggestions that how to solve my problem, Any help much appreciated
My guess would be that the alert in componentDidMount() is empty because it only called once, at a time when data is still empty, while render() is called on each change of state or props.
I would expect the flow of alerts to look something like this:
Alert called from child's render: "data: (empty)"
Alert called from child's didMount: "didMount:(empty)"
User clicks something in parent, state change, re-render triggered
Alert called from child's render: "data: FOO-content"
React does NOT call componentDidMount() on the second pass. If you want your datasource to be populated on EACH update of the child, you will need to add a componentDidUpdate() method to your child, with copy of the code you have inside componentDidMount().
As a general note: I would advise you to read React's explanation of component lifecycle and methods. I have a feeling that the preparation you are doing inside componentDidMount() is probably better placed elsewhere:
creating a DataSource and initial fill with data from props: in getInitialState()
updating Datasource with data from new props: in componentWillReceiveProps()
I found in React generally that if I want to prepare the initial state of my component based on this.props then I should do it in componentDidUpdate instead of componentDidMount. Components aren't mounted with populated props from the parent component, only updated with them.
I noticed this when doing normal React and doing console.log(this.props) in the render method of my child component. It would log initally as empty, then log again populated with the props. If I called a this.setState in componentDidMount then the population of this.props occurs in the third render. This is because calling this.setState in componentDidMount triggered a pre-update render.
I hope this makes sense and applies to your situation - I arrived at your question looking for a solution to similar behaviour.

Resources