Proper way to prefill form fields in React

I’m working on Recipe box challenge, I’m trying to make editing work. I pass the props to form fields. The problem is that each recipe edit form is prefilled with first recipe name and recipe ingredients from array…

Here is Codepen link for code: https://codepen.io/merko30/pen/odzXgO

For example:
First one is hamburger in my localStorage …
If I try to edit ‘pizza’, it opens form with ‘hamburger’ on name field…

It’s not compiling for me: console says: “this.props.recipe is null.” LMK when it compiles.

<a onClick={() => console.log(this.props)}
          className="btn btn-sm btn-light mr-1"
          data-target="#editModal"
          data-toggle="modal"><i className="fa fa-pencil"></i></a>

Here is my console:

deleteRecipe
:
ƒ ()
handleChange
:
ƒ ()
num
:
1
recipe
:
ingredients
:
(2) ["meat", " bread"]
name
:
"Schnitzl"

As you see, name is “Schnitzl” but in edit form it’s “Hamburger”

Sorry, what I meant is: I see nothing on the rendering pane of your Pen. You have rendered <App /> to #app, and you have a render() function inside your App class, but nothing displays. Have you tried viewing your pen from an incognito or private browsing window? I am seeing nothing, and my console is full of errors, not what you report.

I forgot to set few recipes on init, I used localStorage, now it should work.

Hi @merko30

The problem is that you’ve got two Modals generated for each recipe ingredient, but they’re both triggered by the same id: #editModal, so you need a way to distinguish them.

You could do something like this:

<Modal 
	title="Edit recipe"
	dataTarget={this.props.recipe.name + "Modal"}
	dataTargetID={"#" + this.props.recipe.name + "Modal"}
	handleChange={this.props.handleChange}
	recipeName={this.props.recipe.name}
	recipeIngredients={this.props.recipe.ingredients}
/>

<a onClick={() => console.log(this.props)}
	className="btn btn-sm btn-light mr-1"
	data-target={"#" + this.props.recipe.name + "Modal"}

Notice, I changed the hard coded string for dataTarget, dataTargetID and data-target and replaced it with a generated one using the recipe name.

2 Likes

@joesmith100 Thank you so much

1 Like

Ditto @joesmith100: I noticed the flickering, so I added a few console logging lines in the fork I made, and noticed that you are setting dataTargetId=“editModal” for everything, and that it gets rendered 3 times (Hamburger, Pizza, null) on document load. Here’s the link to the fork:

I created a topic about the flickering, I tried with z-index , overflow but can’t figure out what’s wrong…

Also, now I can’t type altough there is onChange method…

I’m not too familiar with Bootstrap, which is why I’m a little hesitant to give advice about their modal implementation, but i did notice that the flicker only happens when I drag the mouse or click. I don’t know if that’s a result of you having stacked modal windows. Hopefully that helps. I am building my projects with React and raw HTML/CSS, so I apologize about not being able to help with what might be Bootstrap issues.

I think the issues is due to where you’re rendering the Modal, I can’t pin down the exact problem but I can see that if you render the model outside the <li> the flickering disappears.

Try this out:

// render method of RecipeList
{this.props.recipes.map((r,i) => {
	return <React.Fragment key={i}>
		<Recipe
			recipe={r} 
			num={i} 
			deleteRecipe={this.props.deleteRecipe}
			handleChange={this.props.handleChange}/>
		<Modal
			title="Edit recipe"
			dataTarget={r.name + "Modal"}
			dataTargetID={"#" + r.name + "Modal"}
			handleChange={this.props.handleChange}
			recipeName={r.name}
			recipeIngredients={r.ingredients}
			{this.props.handleSubmit}
		/>
	</React.Fragment>
})}

Then remove the Modal from the Recipe class.

I should say, the resulting html isn’t good practice as you have div’s that are direct children of a <ul>. You could re-write it to render only one edit Modal at the same level as the addModal, then pass down a function that changes the state of the App class that the modal can use and renders it with the correct values.

1 Like

What’s wrong here:

class RecipeList extends React.Component {
 constructor(props) {
   super(props);
 }
  render() {
    this.props.recipes.map((r,i) => {
	return <React.Fragment key={i}>
		<Recipe
			recipe={r} 
			num={i} 
			deleteRecipe={this.props.deleteRecipe}
			handleChange={this.props.handleChange}/>
		<Modal
			title="Edit recipe"
			dataTarget={r.name+"Modal"}
			handleChange={this.props.handleChange}
			recipeName={r.name}
			recipeIngredients={r.ingredients}
			handleSubmit={this.props.handleSubmit}
		/>
	</React.Fragment>
    })}}

I’m getting this error:
RecipeList(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.

No question marks in codepen, nothing is missing but doesn’t work…

New problem now, I tried to solve it myself but I just started working with React. I set defaultValue on each form field and onChange method, but if I don’t trigger event, type something it will return empty value…

For example:
Hamburger is name, if I don’t edit recipe name, add few ingredients, ingredients are edited but name is “”.