4

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??

2
  • decent discussion here: React - change input defaultValue by passing props only use defaultValue and rerender based on key value. Commented Oct 16, 2021 at 14:20
  • @pilchard btw it's for reactjs but write an answer if you could salvage something from it Commented Oct 16, 2021 at 14:24

8 Answers 8

7
const inputRef = useRef();

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


//function to get input value
const handleSubmit = () => {
    let textInputValue = inputRef.text;
}
Sign up to request clarification or add additional context in comments.

Comments

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;

Comments

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/>)
}

Comments

0

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

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

<TextInput
    value={value}
    onChangeText={setValue}
/>

1 Comment

according to the other answer you can use useRef() to prevent re render
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 ""
}}

3 Comments

could you show a useMemo hook example?
see this on React documentation and this article for more information.
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.
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>
 );

Comments

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}
               />

Comments

0

I also encountered a similar problem, but later I solved it using useMemo hook.

1 Comment

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.

Your Answer

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