2

I have a TextInput and I don't want it to re render every time I change the value inside it

const [WrittenVal,setWrittenVal] = useState(()=>'');
...
    <TextInput
        value={String(WrittenVal)}
        onChangeText={text => setWrittenVal(text)}
    />

but I want to be able to change the value inside the input at the push of a button that's why I haven't just used defaultValue

any solutions??

  • decent discussion here: [React - change input defaultValue by passing props](https://stackoverflow.com/questions/30727837/react-change-input-defaultvalue-by-passing-props) only use `defaultValue` and rerender based on `key` value. – pilchard Oct 16 '21 at 14:20
  • @pilchard btw it's for reactjs but write an answer if you could salvage something from it –  Oct 16 '21 at 14:24

7 Answers7

4
const inputRef = useRef();

<TextInput
   ref={inputRef}
   onChangeText={text => inputRef.text = text }
/>


//function to get input value
const handleSubmit = () => {
    let textInputValue = inputRef.text;
}
Hammad Anwar
  • 119
  • 1
  • 5
3

You can use useRef to save text from text input without render , and useState to show text in input on button press:

Live example : https://snack.expo.dev/TW-fMx1-2

import React from "react";
import { SafeAreaView, StyleSheet, TextInput,TouchableOpacity,Text } from "react-native";

const UselessTextInput = () => {
  const [text, onChangeText] = React.useState("");

  const textRef = React.useRef('')

  const textToRef = (text) =>{
    textRef.current = textRef.current + text
  }

  const showTextInInput = () =>{
    onChangeText( textRef.current )
  }

  console.log("render")
  return (
    <SafeAreaView>
      <TextInput
        style={styles.input}
        onChangeText={textToRef}
        value={text}
      />
      <TouchableOpacity onPress={showTextInInput}>
          <Text>SHOW TEXT IN INPUT</Text>
      </TouchableOpacity>
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  input: {
    height: 40,
    margin: 12,
    borderWidth: 1,
    marginTop:50,
    padding: 10,
  },
});

export default UselessTextInput;
Quintis
  • 517
  • 3
  • 12
1

If you have a nested component situation like the below you need to move the state into the component (under EpicComponent) the setWrittenVal will trigger a re-render on the EpicComponent. Common symptoms are the the field will lose focus when you type.

const Parent = ()=> {
const [WrittenVal,setWrittenVal] = useState(()=>'');
...
    const EpicComponent = ()=> {
        return (   
            <TextInput
                value={String(WrittenVal)}
                onChangeText={text => setWrittenVal(text)}
            /> )
    }
    return (<EpicComponent/>)
}
Yonz
  • 120
  • 6
0

You cannot prevent re-renders on type. But your code can be simplified to:

const [value, setValue] = useState('');

<TextInput
    value={value}
    onChangeText={setValue}
/>
  • according to the other answer you can use useRef() to prevent re render –  Nov 10 '21 at 07:20
0

You can't prevent re-render on input when the value change.

But you can prevent other components to be re-renderd by React.memo or useMemo hook.

And for changing value of input with button press you can do like this:

<Button onPress={() => {
    setWrittenVal(""); //write value you want in ""
}}
Mohamadamin
  • 564
  • 5
  • 16
  • could you show a useMemo hook example? –  Oct 17 '21 at 09:23
  • see [this](https://reactjs.org/docs/hooks-reference.html#usememo) on React documentation and [this article](https://blog.logrocket.com/react-memo-vs-usememo/) for more information. – Mohamadamin Oct 17 '21 at 09:39
  • 1
    React.memo is too much simple for components. justi wrap the component in `React.memo()`. `const component = React.memo((props) => {return ()})` and `useMemo` is used for creating memorizedValue. – Mohamadamin Oct 17 '21 at 09:42
0

By doing this, you both prevent re-render and reset the text input value after clicking the button.


const ref = useRef("");
const inputRef = useRef(null);

const onChangeText = (item) => {
  ref.current = item;
};

const addComment = async () => {
  ref.current = "";
  inputRef.current?.clear();
  // Perform any other actions or logic you need here
};

 return (
   <View>
     <TextInput ref={inputRef} onChangeText={onChangeText} />
     <TouchableOpacity onPress={addComment}>
         <Text>Send</Text>
     </TouchableOpacity>
   </View>
 );
Arty.Simon
  • 844
  • 2
  • 7
  • 21
0

You can prevent re-render only using UseRef. const keyRef = useRef();

const keyToRef = (text)=>{
    keyRef.text = text
           }

               <TextInput 
                ref={keyRef}
                onChangeText={keyToRef}
                value={keyRef?.text}
               />