Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TextInput not adhering to the passed in value prop #18219

Closed
apearce opened this issue Mar 6, 2018 · 19 comments
Closed

TextInput not adhering to the passed in value prop #18219

apearce opened this issue Mar 6, 2018 · 19 comments
Labels
Bug Component: TextInput Related to the TextInput component. Ran Commands One of our bots successfully processed a command. Resolution: Locked This issue was locked by the bot.

Comments

@apearce
Copy link

apearce commented Mar 6, 2018

I updated an app (iOS only) I am working on from 0.49 to 0.54. In my app I am working with currency and enforce during the onChangeText event that what is entered is valid USD. If what the user entered is not the proper format I do not update the TextInput. This was working fine as far as I remember in 0.49 but after the update to 0.54 I can enter things like 'FOO' or 112.23242, neither of which would be a valid USD currency amount. It appears that the TextInput component is no longer setting it's value to the value prop value.

Environment

Environment:
OS: macOS High Sierra 10.13.3
Node: 8.9.4
Yarn: Not Found
npm: 5.6.0
Watchman: 4.7.0
Xcode: Xcode 9.2 Build version 9C40b
Android Studio: Not Found

Packages: (wanted => installed)
react: 16.3.0-alpha.1 => 16.3.0-alpha.1
react-native: 0.54.0 => 0.54.0

Expected Behavior

As it is a controlled component, the TextInput value would match what is passed to the value prop.

Actual Behavior

I can set the value prop to something like "HARDCODED TEXT" and if I enter new text into the TextInput it gets displayed.

Steps to Reproduce

Some sample code loosely based on the TextInput example in the docs showing the issue:

import React, { Component } from 'react';
import { AppRegistry, Text, TextInput, View } from 'react-native';

export default class UselessTextInput extends Component {
  constructor(props) {
    super(props);
    this.state = {};
  }

  render() {
    return (
      <View style={{top:100, margin: 10}}>
        <Text>I would expect this to say Hello! when the user types and then never change</Text>
        <TextInput
          style={{height: 40, marginBottom: 10, borderColor: 'gray', borderWidth: 1}}
          onChangeText={(text) => this.setState({val: 'Hello!'})}
          placeholder="Should lock value to Hello! after first edit"
          value={this.state.val}
        />
        <Text>I would expect this to always say HARDCODED TEXT</Text>
        <TextInput
          style={{height: 40, marginBottom: 10, borderColor: 'gray', borderWidth: 1}}
          value="HARDCODED TEXT"
        />
        <Text>I would expect this to never have a value in it</Text>
        <TextInput
          style={{height: 40, marginBottom: 10, borderColor: 'gray', borderWidth: 1}}
          placeholder="value prop set to a non-existent state"
          value={this.state.foo}
        />
      </View>
    );
  }
}

// skip this line if using Create React Native App
AppRegistry.registerComponent('AwesomeProject', () => UselessTextInput);
@filipef101
Copy link

Can confirm, having same issue

filipef101 referenced this issue Mar 13, 2018
Summary:
This is a complete rewrite of RCTText, the part of React Native which manages Text and TextInput components.

Key points:

* It's understandable now. It follows a simple architectural pattern, and it's easy to debug and iterate. Text flow layout is a first-class citizen in React Native layout system now, not just a wired special case. It also brings entirely new possibilities such as nested interleaving <Text> and <View> components.
* All <Text>-specific APIs were removed from UIManager and co (it's about ~16 public methods which were used exclusively only by <Text>).
* It relies on new Yoga measurement/cloning API and on-dirty handler. So, it removes built-in dirty propagation subsystem from RN completely.
* It caches string fragments properly and granularly on a per-node basis which makes updating text-containing components more performant.
* It does not instantiate UIView for virtual components which reduces memory utilization.
* It drastically improves <TextInput> capabilities (e.g. rich text inside single line <TextInput> is now supported).

Screenshots:
https://cl.ly/2j3r1V0L0324
https://cl.ly/3N2V3C3d3q3R

Reviewed By: mmmulani

Differential Revision: D6617326

fbshipit-source-id: 35d4d81b35c9870e9557d0211c0e934e6072a41e
@react-native-bot react-native-bot added Ran Commands One of our bots successfully processed a command. Component: TextInput Related to the TextInput component. labels Mar 16, 2018
@stale
Copy link

stale bot commented Jun 14, 2018

Hey there, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community's attention? This issue may be closed if no further activity occurs. You may also label this issue as "For Discussion" or "Good first issue" and I will leave it open. Thank you for your contributions.

@stale stale bot added the Stale There has been a lack of activity on this issue and it may be closed soon. label Jun 14, 2018
@ChildishDanbino
Copy link

@filipef101 - I recently upgrade our application to RN 0.54 and can confirm I am still experiencing this issue. Apart from the PR being merged is there a work around?

@stale stale bot removed the Stale There has been a lack of activity on this issue and it may be closed soon. label Jun 26, 2018
@filipef101
Copy link

@Daadler6 ignore my other message. Hmm, that is not stable sadly, IMO best bet is to go to .52

@filipef101
Copy link

@ChildishDanbino
Copy link

@filipef101 - Thanks for the quick response! We are using Expo so I'll try and implement a JS workaround and report back

@lsps9150414
Copy link

@Daadler6 Can you share your js workaround? thanks!

@ram4git
Copy link

ram4git commented Aug 16, 2018

What I did was to generate a random key (timestamp?) and assign as key prop to TextInput to refresh it with the value every time something is input.

@chrisbobbe
Copy link

@ram4git When I do this, the keyboard is dismissed each time the text changes. Has this happened for you?

@adelsz
Copy link

adelsz commented Sep 5, 2018

Confirmed on RN 0.55.4. React Native doesn't support controlled TextInputs, and this haven't changed in 4 months.

@rptwsthi
Copy link

Having Same issue, it works on iOS but not on android.

@adelsz
Copy link

adelsz commented Sep 17, 2018

Looks like this should be fixed in 0.57.
This PR finally made it into a release.

@rptwsthi
Copy link

Having Same issue, it works on iOS but not on android.

In my case issue was with maxLength. I tried -1 (consider I made a reusable component) in case when there were no limit to be set else given limit. This pattern worked with iOS but blew in case of android. I have applied a conditional check only for this prop with this looks ridiculous but what can we do.

render () {
    return (
      <View style = {_gstyle.formEditContainer}>
        <Text style = {_gstyle.formTitleText}>{(this.props.title) ? this.props.title : ''}</Text>
        {
          (this.props.maxLength) ? 
            <TextInput style = {[_gstyle.formTextInput]}
            value = {this.state.value+""}
            maxLength = {(this.props.maxLength) ? this.props.maxLength : -1}
            placeholder = {(this.props.placeHolder) ? this.props.placeHolder : ""}
            autoCapitalize = {(this.props.autoCapitalize) ? this.props.autoCapitalize : 'none'}
            multiline = {(this.props.multiline) ? this.props.multiline : false}
            returnKeyType = {(this.props.returnKeyType) ? this.props.returnKeyType : "default"}
            keyboardType = {(this.props.keyboardType) ? this.props.keyboardType : 'default'}
            onChangeText = {(text) => this.setState({value:text})}
            secureTextEntry= {(this.props.secureTextEntry) ? this.props.secureTextEntry : false}
            placeholderTextColor = "#DDDDDD"
            underlineColorAndroid = "transparent"
            editable = {(this.props.editable != null) ? this.props.editable : true}
            onEndEditing={(e) => this.textEdittingEnded(e)}
            textAlign = 'right'
            />
          :
          <TextInput style = {[_gstyle.formTextInput]}
            value = {this.state.value+""}
            // maxLength = {(this.props.maxLength) ? this.props.maxLength : -1}
            placeholder = {(this.props.placeHolder) ? this.props.placeHolder : ""}
            autoCapitalize = {(this.props.autoCapitalize) ? this.props.autoCapitalize : 'none'}
            multiline = {(this.props.multiline) ? this.props.multiline : false}
            returnKeyType = {(this.props.returnKeyType) ? this.props.returnKeyType : "default"}
            keyboardType = {(this.props.keyboardType) ? this.props.keyboardType : 'default'}
            onChangeText = {(text) => this.setState({value:text})}
            secureTextEntry= {(this.props.secureTextEntry) ? this.props.secureTextEntry : false}
            placeholderTextColor = "#DDDDDD"
            underlineColorAndroid = "transparent"
            editable = {(this.props.editable != null) ? this.props.editable : true}
            onEndEditing={(e) => this.textEdittingEnded(e)}
            textAlign = 'right'
          />
          }
        <EditFormCellSeprator />
      </View>
      );
    } 

@reyalpsirc
Copy link
Contributor

@rptwsthi if you set it as undefined instead of -1, doesn't it work for Android? Because if so, you don't need the duplicated code.

@rptwsthi
Copy link

@rptwsthi if you set it as undefined instead of -1, doesn't it work for Android? Because if so, you don't need the duplicated code.

undefined it is then thanks @reyalpsirc you have made my life easy. Coming from mainly swift background my hands are tight with javascript.

@devpascoe
Copy link

Using lodash's clone method helped me ensure i was not reusing the same objects in redux. _.cloneDeep

Once applied my props were updated as i expected and the TextInput behaved accordingly.

@michalchudziak
Copy link
Contributor

Hello there 👋 this issue seems to have been inactive for the past few weeks. Because of this, it's likely that the issue is not a high priority anymore or it has been solved by OP; for these reasons, we'll close it. But please, if it's actually still an issue with 0.59 please comment below and we can reopen it or please send us a Pull Request with a fix 😊

@saulve
Copy link

saulve commented Oct 11, 2019

This is issue is definitely still present on RN 0.59.10. I have something similar to this:

handleBlur = (evt) => {
  const {text} = evt.nativeEvent;
  if (!text) {
    return;
  }
  return this.props.updateState(text); // <- this updates the 'text' prop on the parent
}
render() {
 return (
<TextInput
  value={this.props.text}
  onBlur={this.handleBlur}
/>
)}

What I get:
After I delete all text from input and click out, the TextInput remains empty.

What I expect:
After I click out I expect the TextInput to be filled with the unchanged value from the props. After blur I get a re-render and I can see that this.props.text is correctly set to the original unchanged value from the parent, however, the text input remains empty (not using the value from the props). However, if I do change the state on the parent, the input gets rendered as expected.

TL;DR: It seems that during consecutive re-renders TextInput's value does not change to represent the props even though the value inside TextInput's box differs.

@facebook facebook locked as resolved and limited conversation to collaborators Mar 19, 2020
@react-native-bot react-native-bot added the Resolution: Locked This issue was locked by the bot. label Mar 19, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Bug Component: TextInput Related to the TextInput component. Ran Commands One of our bots successfully processed a command. Resolution: Locked This issue was locked by the bot.
Projects
None yet
Development

No branches or pull requests