简体   繁体   中英

How can I concatenate a value on the second character of an array using useState();

I'm working on a React native project, and I'm using the useState hook and the TextInput property to store the user's input, I associate these inputs to a text component so that they are rendered and displayed every time the user types a number.

const BMIcalculator = () => {
  const [state, setState] = useState([""]);

  function userHeightHandler(value) {

    for (var i = 0; i < value.length; i++) {
  
      if (value[i].length == 1) {

         var res = value.splice(1, 0, ".");

         setState(res.join(""));
      
      }

    }
    setState(value);

    return (
     
    <View style={styleInside.heightContentValue}>
          <Text style={{ justifyContent: "center", fontSize: 22 }}>
            {"text: " + state +}
          </Text>
    </View>

    <View style={styles.input}>
          <Input
            style={styles.inputs}
            placeholder="text"
            maxLength={3}
            onChangeText={(value) => userHeightHandler([value])}
            }
          />
        </View>

    
    
    )

}

My goal is to be able to concatenate a "." after the first character the user types, and have this value remain until removed, how could I do this? It may seem like a simple thing, but it's taken me all day trying to figure it out, I'd appreciate any advice or help in advance.

If I understand correctly, you want to add a "." at the end of the user input when its length is equal to one.

Try this:

const BMIcalculator = () => {
  const [state, setState] = useState([""]);

  function userHeightHandler(value) {
    value?.length === 1 ? setState(value + ".") : setState(value);
  }

  return (
    <>
      <View style={styleInside.heightContentValue}>
        <Text style={{ justifyContent: "center", fontSize: 22 }}>
          {"text: " + state}
        </Text>
      </View>

      <View style={styles.input}>
        <Input
          style={styles.inputs}
          placeholder="text"
          maxLength={3}
          value={state}
          onChangeText={(value) => userHeightHandler(value)}
        />
      </View>
    </>
  );
};

You can see a working example in React: CodeSandBox

So if I understand correctly, what you try to achieve is to insert a '.' character after the first character of your input as long as your input has at least one character?

Here is how it could be done assuming you don't want to update the input value itself but just the state that is displayed in the Text block.

const BMIcalculator = () => {
  const [state, setState] = useState([""]);

  function userHeightHandler(value) {
    let newValue = value;
    if (value.length === 1) {
      newValue += '.';
    } else if (value.length > 1) {
      newValue = value.charAt(0) + '.' + value.slice(1, value.length);
    }
    setState(newValue);
  }

    return (
    <>
    <View style={styleInside.heightContentValue}>
          <Text style={{ justifyContent: "center", fontSize: 22 }}>
            {"text: " + state +}
          </Text>
    </View>

    <View style={styles.input}>
          <Input
            style={styles.inputs}
            placeholder="text"
            maxLength={3}
            onChangeText={(value) => userHeightHandler(value)} // no need to wrap value with an array
            }
          />
        </View>
    </>
    )
}

Note if you want to update the input itself, you would probably need more advance stuff like handling the cursor after the user inputs the first character or handling backspace behaviour when the user presses it from behind the first character or behind the . character. Additionally you might want to add some checks so that the user can only input numbers.

If you don't care about edge case or weird caret behaviour, you can do the following:

const BMIcalculator = () => {
  const [state, setState] = useState([""]);

  function userHeightHandler(value) {
    let newValue = value;
    newValue = newValue.replaceAll(".", ""); // remove all `.` characters
    // then insert it at the right place
    // second condition is to allow backspace on `.` character
    if (newValue.length === 1 && !(value.length === 1 && state.length === 2)) {
      newValue += ".";
    } else if (newValue.length > 1) {
      // insert '.' after first character, then add the rest of the value
      newValue = newValue.charAt(0) + "." + newValue.slice(1, value.length);
    }
    setState(newValue);
  }

  return (
    <>
      <View style={styleInside.heightContentValue}>
        <Text style={{ justifyContent: "center", fontSize: 22 }}>
          {"text: " + state}
        </Text>
      </View>
      <View style={styles.input}>
        <Input
          style={styles.inputs}
          placeholder="text"
          maxLength={4}
          value={value}
          onChangeText={(value) => userHeightHandler(value)} // no need to wrap value with an array
        />
      </View>
    </>
  );
};

Both, using a [""] for your state and your userHeightHandler look way too complicated to me.

My goal is to be able to concatenate a "." after the first character the user types, and have this value remain until removed

something like this?

 const input = document.getElementById("foo"); let prev = input.value; input.oninput = e => { let value = e.target.value; value = (prev === value + ".")? "": value.replace(/\D+/g, ""); e.target.value = prev = value && value[0] + "." + value.slice(1,3); }
 <input id="foo">

this shouldn't be too hard to translate to react. something like

const [state, setState] = useState("");

onChangeText={value => setState(prev => (prev === value + ".") ? "" : (value = value.replace(/\D+/g, "")) && value[0] + "." + value.slice(1,3))}

You even get prev for free when doing setState(prev =>...)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM