Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

184
Views
How to prevent setting a state variable to another state variable?

I have a controlled component that I call Note. I want its default value to be equal to the selected note (which is set in App.js and passed through as a prop). It seems redundant/bad practice. Here's my code, simplified to the relevant parts. How can I set the default value of textarea to be equal to another state variable?

Edit: Forgot to mention that selectedNote is changed in another component. It works for the state set in useEffect but not for the updates.

App.js

function App(){
  const [selectedNote, setSelectedNote] = useState("")
    
  useEffect(() => {
    async function fetchData(){
      let req = await fetch("http://localhost:9292/notes");
      let res = await req.json();
      setSelectedNote(res[0])
    }
    fetchData()
  },[])

  return (
    <Note selectedNote={selectedNote.body}/>
  )
}

Note.js

function Note({selectedNote}) {
  const [editValue, setEditValue] = useState(selectedNote)

  return (
    <form>
      <textarea value={editValue} onChange={handleChange}>
      </textarea>
    </form>
  )
}

(To clarify, I have no issues if I write const [editValue, setEditValue] = useState("testing123") or some other string)

about 4 years ago · Juan Pablo Isaza
2 answers
Answer question

0

So ideally you want to lift state up so that the parent component manages the state updates, and the Notes component is as dumb as possible.

In this example the data is loaded into state, and then the notes are built, only receiving an id, some body text which will be their value, and an onChange handler.

When the text is changed, the state is copied, the object in the array (defined by the id) updated, and the new array pushed back into state.

const { useEffect, useState } = React;

const json = '[{"id":1,"body":"Note1"},{"id":2,"body":"Note2"},{"id":3,"body":"Note3"}]';

function mockApi() {
  return new Promise(res => {
    setTimeout(() => res(json), 2000);
  });
}

function Example() {

  const [ notes, setNotes ] = useState([]);
  const [ selectedNote, setSelectedNote ] = useState(null);

  useEffect(() => {
    mockApi()
      .then(res => JSON.parse(res))
      .then(data => setNotes(data));
  }, []);

  function handleChange(e) {
    const { value, dataset: { id } } = e.target;
    const copy = [...notes];
    copy[id - 1].body = value;
    setNotes(copy);
  }
  
  function handleClick() {
    console.log(JSON.stringify(notes));
  }
  
  if (!notes.length) return 'Loading';

  return (
    <div>
      {notes.map(note => {
        return (
          <Note
            key={note.id}
            id={note.id}
            body={note.body}
            handleChange={handleChange}
          />
        )
      })}
      <button onClick={handleClick}>
        View state
      </button>
    </div>
  );

}

function Note({ id, body, handleChange }) {
  return (
    <textarea
      data-id={id}
      value={body}
      onChange={handleChange}
    />
  );
}

ReactDOM.render(
  <Example />,
  document.getElementById('react')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>

about 4 years ago · Juan Pablo Isaza Report

0

You can provide a function to useState that will only be invoked once, when the component renders. Use that function to copy the prop value into the Note's private state.

const [editValue, setEditValue] = useState(() => selectedNote)

You may have other problems, such as the prop value being blank on initial render, but this is still usually the most straightforward way to initialize a private state var based on a prop.

If it turns out that blank-initial-state is an insurmountable problem, then you may instead need to set up a useEffect that updates the private state when the prop value changes to a satisfactory value. Something like this:

const [editValue, setEditValue] = useState()
React.useEffect(() => {
    // only update state if old is blank & new is not
    if(!editValue && selectedNote) setEditValue(selectedNote)
}, [selectedNote])
about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!