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>
)
}
}
Related
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 trying to implement React Native's CheckBox component but can't seem to get it unchecked after changing its value the first time- it's perpetually checked. I understand that the value prop must be set for it to reflect user actions, so I'm trying to setState onChange... what am I getting wrong? :/
export const ReviewCardCheckBox = (props) => {
this.state = { checked: false };
return (
<View style={styles.sectionStyle}>
<View style={{justifyContent: 'flex-start', flex:1}}>
<Text style={styles.fontStyle}>{props.option}</Text>
</View>
<View style={{flexDirection: 'row', justifyContent: 'flex-end', flex:1}}>
<CheckBox onChange={ () => this.setState( {checked: !this.state.checked} )}/>
</View>
</View>
)
};
Thanks for the help!
What you have is a stateless functional component. The purpose of these components is just to receive props and do something with them.
Learn more about the difference here
This function is a valid React component because it accepts a single “props” (which stands for properties) object argument with data and returns a React element. We call such components “functional” because they are literally JavaScript functions.
For you to have state you must do
class ReviewCardCheckBox extends React.Component {
constructor(props) {
super(props);
this.state = { checked: false };
}
render() {
// do what you want.
}
}
You are declaring a Stateless component (a function) so this Component can't have state, as well as it can't setState.
Declare the Component as class instead.
export class ReviewCardCheckBox extends React.Component{
constructor(props){
super(props);
this.state = {chacked: false};
}
render(){
return (
//do something here
);
}
}
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}.