2

Im running into an issue where the onChange={} on <input /> doesn't change the value through state.

I have two Components, Component 1 passes the the state of an input value to Component 2 as a prop:

Component 1:

function MainContent() {
  const [inputValue, setInputValue] = React.useState("");

  const onChangeHandler = (event) => {
    setInputValue(event.target.value);
  };

  return (
    <>
      <input
        id="shtitle"
        value={inputValue}
        onChange={onChangeHandler}
        className="input sh-input"
        type="text"
        placeholder="Incident Title"
      />

      <DuplicateHubDisplay
        data={[
          inputValue,
          momentDate.format("DD/MM/YYYY HH:mm A"),
          textareaValue,
        ]}
      />
    </>
  );
}

export default MainContent;

Component 2: Gets the prop data from Component 1

  const [commsTitle, setCommsTitle] = useState("");
// const [commsTitle, setCommsTitle] = useState(duplicateHubData.data[0]); //Does not work
  
<input
 id="duplicatehub-title"
 value={duplicateHubData.data[0]}
 className="input"
 placeholder="Incident Title"
/>

I don't know how to store duplicateHubData.data[0] as a state and then use onChange to change the state value.

Doing this does not allow me to change the input value:

const DuplicateHubDisplay = (duplicateHubData) => {
    const [commsTitle, setCommsTitle] = useState(duplicateHubData.data[0]);

    return (
      <input
        id="duplicatehub-title"
        onChange={(e) => {
          setCommsTitle(e.target.value);
        }}
        value={commsTitle}
        className="input"
        placeholder="Incident Title"
      />
    );
}
export default DuplicateHubDisplay;

Thanks in advance

8
  • That third option should certainly allow you to update the commsTitle state. What or how are you verifying/validating that state isn't updating? In the least you should see the updated state in the input when you are typing. What is duplicateHubData in the second component? Commented Apr 29, 2021 at 23:29
  • The third method, allows me to update state for sure, however it doesn't contain the data that was provided via duplicateHubData.data[0] to begin with. Not too sure if something like that needs to wrapped in a useEffect or something so that it renders? Commented Apr 29, 2021 at 23:32
  • Can you show us what duplicateHubData.data[0] is and where it comes from? Can you also share how the two component snippets relate? Commented Apr 29, 2021 at 23:33
  • Is component 2 actually DuplicateHubDisplay and being rendered by some other component 1? Commented Apr 29, 2021 at 23:39
  • Correct, DuplicateHubDisplay is definitely component 2 and component 1 renders DuplicateHubDisplay and passes in those props. duplicateHubData.data[0] is the input state from Component 1. Basically im trying to replicate Component 1's input value to Component 2's input. The second method by passing in the value={duplicateHubData.data[0]} replicates Component 1's value, but it doesn't allow me to make edits. the third method by using state, doesn't even show Component 1s input value however it allows me to update the values Commented Apr 29, 2021 at 23:50

1 Answer 1

2

If I understand correctly you want DuplicateHubDisplay's commsTitle state to update when either (1) the inputValue of the parent component updates or (2) the input value in DuplicateHubDisplay updates.

Issue

DuplicateHubDisplay is passed a data prop where the initial inputValue state value is "", so the initial commsTitle state is also "". DuplicateHubDisplay doesn't "listen" for updates to props to then update the commsTitle state.

Solution

<DuplicateHubDisplay
  data={[
    inputValue,
    momentDate.format("DD/MM/YYYY HH:mm A"),
    textareaValue,
  ]}
/>

Yes, use an useEffect hook to react to prop value changes and update the local commsTitle state.

const DuplicateHubDisplay = ({ data }) => {
  const [inputValue] = data; // array destructuring assignment
  const [commsTitle, setCommsTitle] = useState(inputValue);

  useEffect(() => {
    setCommsTitle(inputValue);
  }, [inputValue]);

  return (
    <input
      id="duplicatehub-title"
      onChange={(e) => setCommsTitle(e.target.value)}
      value={commsTitle}
      className="input"
      placeholder="Incident Title"
    />
  );
}

Edit reactjs-input-onchange-not-updating-state

Solution 2

If you don't need to actually do anything with the commsTitle state you can assign data[0] as a defaultValue on the input and use the data[0] value as a React key so when the value updates from the parent React will remount/reset the input with a new default value.

const DuplicateHubDisplay = ({ data }) => {
  const [inputValue] = data; // array destructuring assignment

  return (
    <input
      key={inputValue}
      id="duplicatehub-title"
      defaultvalue={inputValue}
      className="input"
      placeholder="Incident Title"
    />
  );
}

Edit reactjs-input-onchange-not-updating-state #2

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

2 Comments

Unfortunately the solution doesn't work as the ```onChange={(e) =>{setCommsTitle(e.target.value)}} doesn't actually allow me to make changes to the input value. Doing a console.log on useEffect, it seems that it re-renders whatever is being set in the parent element and thus not allowing new values to be set
I made a little typo with useEffect, thanks heaps for your solution. The first one worked for me

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.