I'm a newbie to React-Native, so I've been going through a tutorial to create a login screen. The code in the tutorial is out of date. I'm creating a login screen made up of a few components. However, a certain TextInput isn't showing up in the simulator. Here's the parent component "LoginForm" from LoginForm1.js:
export default class LoginForm extends Component {
constructor(props) {
super(props);
this.state = {
text: ''
};
}
render() {
return (
<Card>
<CardSection>
<Input
placeholder="user#gmail.com"
label="Email"
value={this.state.email}
onChangeText={text => this.setState({ text })}
/>
</CardSection>
The child component "Input" is wrapped in components "CardSection" and "Card" (these pass their props with a View displaying {this.props.children}, but here's the "Input" component from Input.js:
export default class Input extends Component {
render() {
return (
<View style={styles.containerStyle}>
<Text style={styles.labelStyle}>{this.props.label}</Text>
<TextInput
placeholder={this.props.placeholder}
autoCorrect={false}
style={styles.inputStyle}
value={this.props.value}
onChangeText={this.props.onChangeText}
/>
</View>
);
}
}
const styles = StyleSheet.create({
inputStlye: {
color: '#000',
paddingRight: 5,
paddingLeft: 5,
fontSize: 18,
Height: 50,
Width: 50,
flex: 2,
},
This code doesn't throw any errors, but the TextInput from "Input" doesn't show up. I've given it some dimensions in the styling, so that can't be it. If I replace the TextInput with just normal Text, then the contents of that Text tag will appear in the simulator. Am I missing something to do with passing props? Any help would be much appreciated, thank you!
You have the value being passed down as value={this.state.email}, but you're onChangeText is updating this.state.text so just change it to value={this.state.text}.
Related
I'm studying react native version 5 and I would need a short but working example of two files.js, for example App.js and Receiver.js where:
in App.js you can insert a text through Text Input
in Receiver.js it receives and shows the text inserted once have been passed as state and parameter by the previous page.
Can anyone help me?
App.js
export default class App extends Component {
state = {
username: 'demo'
};
render() {
return (
<Text style={Style.label}>User Name</Text>
<TextInput
style={Style.input}
placeholder="UserName"
onChangeText={(value) => this.setState({username: value})}
value={this.state.username}
/>
<Button
title="LOGIN"
onPress={() => this.props.navigation.navigate("Receiver", {username: this.state.username}) }
/>
);
}
}
Receiver.js
export default class Receiver extends Component {
render() {
const { username} = this.props.route.params;
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>User Name: {username}</Text>
</View>
);
}
}
A small suggestion: Read the official document before beginning.✌️
https://reactnavigation.org/docs/params/
I've tried a few methods to get setState() to update the value of state. Currently the text in the <TextInput> changes, but the value in this.state doesn't change.
I have the console.log in the right place, I've tried writing external functions, I've messed around with the variable's names but nothing seems to work.
import * as React from 'react';
import { View, Text, TextInput, TouchableHighlight, Dimensions, StyleSheet } from "react-native";
import PropTypes from "prop-types";
class EditNote extends React.Component{
constructor(props){
super(props)
this.state = {
title: '',
text: '',
id: ''
}
}
// TODO: Change textboxes to match the props from the NoteList
static getDerivedStateFromProps(props){
return(
{...props.route.params}
)
}
render(){
return(
<View style={s.container}>
<View style={s.titleContainer}>
<Text style={s.titleText}>Edit Note</Text>
<View style={{flex: 1}}/>
</View>
<View style={s.inputContainer}>
<TextInput
style={{...s.input, ...s.titleInput}}
autoCapitalize='words'
keyboardAppearance='dark'
placeholderTextColor='#DDD'
onChangeText={(title) => { this.setState({title: title}, () => console.log(this.state)) }}
defaultValue={this.state.title}
/>
<TextInput
style={{...s.input, ...s.textInput}}
autoCapitalize='sentences'
keyboardAppearance='dark'
placeholderTextColor='#DDD'
multiline
onChangeText={(text) => { this.setState({text: text}, () => console.log(this.state)) }}
defaultValue={this.state.text}
/>
</View>
<View style={s.buttonContainer}>
<TouchableHighlight
style={s.backButton}
onPress={() => this.props.nav.navigate('NoteListView')}
underlayColor='#300030'
>
<Text style={s.buttonText}>Cancel</Text>
</TouchableHighlight>
<TouchableHighlight
style={s.addButton}
onPress={() => {
console.log(this.state.note)
this.props.nav.navigate('NoteListView', {note: this.state, mode: 'edit'})
}}
underlayColor='#300030'
>
<Text style={s.buttonText}>Edit</Text>
</TouchableHighlight>
</View>
</View>
)
}
}
export default EditNote
I just realized that this is a problem with two parts.
The first problem is that props.route.params is unaffected by subsequent render() calls. This means that even if you re-render the component, the same initial properties are used.
The second is getDerivedStateFromProps(). Every time the render function is called it calls getDerivedStateFromProps() right before it which sets the state to the initial route parameters.
This problem can be fixed by:
Clearing the initial route parameters in the render function after their initial use. Something a little like this at the beginning of the render()function will work. this.props.route.params = undefined
Using an if statement and a variable in state to regulate when the props should update the state.
Refactor the code to make use of the props
Option 3 is how things should be correctly done but the best solution depends on how your code works.
I am trying to create rich text editor that will have options like click to bold how can i achieve this without affecting previous content when i attempt to change them from state it ends up affecting previous inserted text`
export default class App extends React.Component {
constructor(props){
super(props)
this.state={
text:'',
inputStyles:{
fontWeight:'light'
}
}
}
_Bold =()=>{
this.setState({inputStyles:{
fontWeight:'bold'
}})
}
render() {
return(
<View style={styles.container}>
<StatusBar backgroundColor="#24292e" barStyle="light-content" />
<TextInput placeholder="Star to write"
style={this.state.inputStyles}
/>
<TouchableOpacity onPress={()=>this._Bold()}>
<Text>BOLD</Text>
</TouchableOpacity>
</View>
)
}
}
`
If I understood correctly, I think you have to change your TextInput as following:
<TextInput
placeholder="Star to write"
value={this.state.text}
onChangeText={(text) => this.setState({text)}
style={this.state.inputStyles}
/>
The problem is that you are not storing the text into the state, once it gets rendered it gets lost
I'm building a simple form in React Native. What I'm trying to do is that when the value of the input field changes, I want to update the state (phone in this case). The value of the input field always equals the value of a state. However, when the value of the input field changes, the value of the state(phone) is not updated. Thanks in advance. Here is the code.
import React from 'react';
import { StyleSheet, TextInput, View } from 'react-native';
const styles = StyleSheet.create({
input: {
padding: 5,
borderColor: 'black',
borderWidth: 1,
},
});
export default class AddContactForm extends React.Component {
state = {
phone: 'sdfksd',
};
handlePhoneChange = (phone) => {
this.setState({
phone: '111',
});
};
render() {
return (
<View style={{ paddingTop: 40 }}>
<TextInput
style={styles.input}
value={this.state.phone}
onChangeText={this.handlePhoneChange}
keyboardType="numeric"
placeholder="Phone"
/>
</View>
);
}
}
UPDATED: Even though I set phone in handlePhoneChange, I still can update the text field to a different value apparently. That's inconsistent between the state and the text field.
onChangeText takes a callback.
So in your case pass the input to your function like this
onChangeText={ val => this.handlePhoneChange(val)}
Change your handle function like this.
handlePhoneChange = (phone) => {
this.setState({
phone: phone
})
}
I'm using React native and I want to use Redux-Form to submit text from TextInput following this article,
It works as expected if I enter the text, but when I set the value property of TextInput to some string, after submitting I get an empty object.
It only works when I enter the text, but not when I set it to some value.
here is the part of the TextInput I use:
const titleField = (input, inputProps) => {
var myval = 'test';
return (
<View style={{flexDirection: 'row'}}>
<Label style={{padding: 5}}>Task Title:</Label>
<TextInput
style={styles.inputStyle}
{...inputProps}
onChangeText={input.onChange}
onBlur={input.onBlur}
onFocus={input.onFocus}
value={myval} // get {} when checking the log input after submitting
/>
</View>
)
}
Hope you can help me with that,
Thank you.
I solved this by changing the functional component to a class component and used componentDidUpdate() lifecycle method to check if the props has changed when passing them to the component and call this.props.input.onChange(this.props.value); because input can be invoked with a value also, therefore this.props.value is passed.
From Redux Form API (Field Component):
input.onChange(eventOrValue)
A function to call when the form field is changed. It expects to either receive the React SyntheticEvent or the new value of the field.
This is the whole class component:
class CounterField extends React.Component {
constructor(props){
super(props);
}
componentDidUpdate(){
this.props.input.onChange(this.props.value);
}
render(){
return (
<View style={{paddingTop: 20, width: 30}}>
<TextInput
name='title'
onChangeText={this.props.input.onChange}
editable={false}
value={this.props.value}
style={{fontSize: 20, textAlign: 'center', fontWeight: 'bold'}}
placeholder={'0'}
/>
</View>
)
}
}