0

I have a form component in my react app that can be used to create or update recipes depending on the route. The create functionality works fine, but the update is giving me trouble.

I pass fetched data into the component using props here is what the JSON looks like:

{
   method: "Cook the guanciale in a large skillet over medium heat until deeply golden 
           (adjust the heat as necessary to render the fat [...]
   name: "Pasta Alla Gricia"
}

I am trying to get the name to prefill into the form's name <input> and the method to prefill into the form's method <textarea>. I tried doing this with useEffect(), with:

 useEffect(() => {
    setName(props.data.name)
    setMethodStepsList(props.data.method)
  })

while it prefilled the name input it then locked the value to that. The method did not prefill the textarea at all.

I am pretty stumped with this one, and would be grateful for any assistance.

export default function Recipe(props) {
  const [name, setName] = useState('')
  const [methodStepsList, setMethodStepsList] = useState('')
  const [methodStepObject, setMethodStepObject] = useState([])
  const [ingredientList, setIngredientList] = useState([])
  const [ingredientObject, setIngredientObject] = useState({
    ingredient_name: '',
    quantity: '',
    measure: '',
  })

  const formLabel = props.data ? 'Update Recipe' : 'New Recipe'
  useEffect(() => {
    setName(props.data.name)
    setMethodStepsList(props.data.method)
  })

  //new recipe logic
  [...]

  return (
    <div>
      <div className="recipe-form-container">
        <form className="recipe-form">
          <div className="page-header">
            <h1>{formLabel}</h1>
          </div>

          {/* recipe name logic */}
          <div className="recipe-title recipe-element">
            <label>Recipe Name</label>
            <input
              type="text"
              value={name}
              onChange={(e) => setName(e.target.value)}
            ></input>
          </div>

          //recipe method logic
          <div className="recipe-blurb recipe-element">
            <label>Recipe Method</label>
            <span className="method-span">
              <textarea
                rows="5"
                name="step_instructions"
                type="text"
                placeholder="Method will be split up based on new lines"
                onChange={(e) => handleMethodChange(e)}
              ></textarea>
              <button
                onClick={(e) => {
                  console.log(methodStepObject)
                  setMethodStepsList(methodStepObject)
                  e.preventDefault()
                }}
              >
                Add Method
              </button>
          
         [...]

}

deadant88
  • 920
  • 9
  • 24

2 Answers2

0

Please remove useEffect statements and try like this

const [name, setName] = useState(props.data.name)
const [methodStepsList, setMethodStepsList] = useState(props.data.method)

devcrazy
  • 505
  • 5
  • 14
  • Thanks for the response. It looks like the props get passed down from the parent component twice, once they are empty objects and the second time they have the data. You can see [here](https://ibb.co/r25KfdN) so it initializes as empty. – deadant88 Jun 20 '22 at 07:59
0

You should be careful while initializing state with props in React. See React component initialize state from props

class Recipe extends React.Component {

    constructor(props) {
        super(props)
        this.state = {name:'', method:'', ingredients: []};
    }

    static getDerivedStateFromProps(props,state) {
        return {name: props.data.name, method: props.data.method};
    }

    render() {
        return <div>...</div>
    }
}
Nice Books
  • 1,675
  • 2
  • 17
  • 21