0

I'm using React Native and I have these functions. renderInputs() generates some inputs fields while getNextWord() does some things which are not relevant and moreover it updates the states.

getNextWord() {
   // do some stuff    
   this.setState({ set states here }); 
}

renderInputs() {
    var products = []
    // some code that generates a randomNumber
    for (let p = 0; p < randomNumber; p++){
       products.push (<TextInput defaultValue="" maxLength={1} key={p}  onChangeText={(text) => this.handleChange(text, p)}></TextInput> );
    }
    return products
}

In my render() method I show the input fields and I placed I button that everytime is clicked it triggers getNextWord() function.

<View>{this.renderInputs()}</View>
<Button onPress={this.getNextWord.bind(this)}>Get Next Word</Button>

Now, I can correctly see the input fields, and everytime I click on "Get Next Word" button renderInputs() generates a new bunch of input fields.

My problem is that if I type a character inside one of these input field once I click button I still see that letter, while I'd like to have all my input fields empty at the beginning.

I tried using defaultValue="" but it seems it doesn't work. If I do: defaultValue="A" this is what I get once I run the app.

example:

First time renderInputs() is called:

_ _ _ _ _ _ // empty inputs (let's say randomNumber is 6)

then I type in the second input field a letter, let's say "G"

_ G _ _ _ _

once I click "Get Next Word" button renderInputs() generates randomNumber (let's say generated randomNumber is 8) input fields and this is what I get:

A G A A A A A A

but I want to have:

A A A A A A A A

1 Answer 1

1

Here's my complete solution, followed by an explanation:

class MyComponent extends Component {

  // initial state
  state = {
    inputsNumber: this.randomInputs()
  }

  getNextWord() {
    // do some stuff
    const nextInputNumber = this.randomInputs()
    const inputsState = {}

    // set all inputs to A
    for (let p = 0; p < nextInputNumber) {
      inputsState[this.inputKey(p)] = 'A'
    }
    // set new random number of inputs
    this.setState({
      ...inputsState
      inputsNumber: nextInputNumber,
      // set rest of state here if needed ...
    });
  }

  renderInputs() {
    var products = []
    // some code that generates a randomNumber
    for (let p = 0; p < this.state.inputsNumber; p++){
       products.push(
        <TextInput
          maxLength={1}
          key={p}
          onChangeText={(text) => this.handleChange(text, p)}
          value={ this.state[this.inputKey(p)]}
        />
      );
    }
    return products
  }

  handleChange (text, p) {
    this.setState({
      [this.inputKey(p)]: text
    })
  }

  randomInput () {
    return Math.floor(Math.random() * 8) + 1 // or whatever random function
  }

  inputKey (p) {
    return 'input ' + p
  }
}

First thing first:
I don't think u want to generate the random number in the render function. This means every time render will get called, the number of inputs would change, and that would lead to a very bad UX, since render (potentially) gets called on every state change. So use the state to keep track of that number:

import React, { Component } from 'react'
class MyComponent extends Component {

  // initial state
  state = {
    inputsNumber: this.randomInputs()
  }

  getNextWord() {
     // do some stuff
     this.setState({
      inputsNumber: this.randomInputs(),
      // set rest of state ...
    }); 
  }

  randomInput () {
    return Math.floor(Math.random() * 8) + 1 // or whatever random function
  }
}

Now to use your inputs correctly u need to bound their values to the state as well:

renderInputs() {
  var products = []
  for (let p = 0; p < this.state.inputsNumber; p++){
     products.push(
      <TextInput
        maxLength={1}
        key={p}
        onChangeText={(text) => this.handleChange(text, p)}
        value={this.state[this.inputKey(p)]}
      />
    );
  }
  return products
}

handleChange (text, p) {
  this.setState({
    [this.inputKey(p)]: text
  })
}

inputKey (p) {
  return 'input ' + p
}

Now to "reset" all inputs to the letter A, we need to do a slight modification to the click event:

getNextWord() {
  // do some stuff
  const nextInputNumber = this.randomInputs()
  const inputsState = {}

  // set all inputs to A
  // since we don't know how many inputs we have, we use the 'nextInputNumber' we just generated.
  for (let p = 0; p < nextInputNumber) {
    inputsState[this.inputKey(p)] = 'A'
  }
  // set new random number of inputs
  this.setState({
    ...inputsState
    inputsNumber: nextInputNumber,
    // set rest of state here if needed ...
  });
}

NOTE: I havent tested this. If something doesn't work, create a fiddle and I will modify it to a working example

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for your time and the answer, finally I solved it using the method clear(0)
I'm guessing u r new to programming and SO :) I have no idea what clear(0) means. Glad u found a solution!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.