Hello, just taking a quick look…
First of all, yes, your code is a mess. Get in the habit of maintaining your code as you go. I am an inherently messy person (not dirty, just let things fall into disarray) … except when I code. Experience has taught me that this leads to nightmares. Codepen will auto indent for you if you select the code and shft-tab. Also, on the top right corner of the JS pane is a little down arrow for a pulldown menu that has some nice code cleaners. Tidy JS works nicely.
Opening up your console, I find some errors. (Please, please people, learn to read the browser console, it is your best tool, second only to coffee!)
For example, I get:
react-dom.min.js:14 Uncaught ReferenceError: evt is not defined
at RecipeBox.handleChange (VM187 pen.js:126)
at Object.executeOnChange (VM186 react-dom.min.js:12)
at h.o (VM186 react-dom.min.js:13)
at Object.r (VM186 react-dom.min.js:14)
at a (VM186 react-dom.min.js:12)
at Object.s [as executeDispatchesInOrder] (VM186 react-dom.min.js:12)
at f (VM186 react-dom.min.js:12)
at m (VM186 react-dom.min.js:12)
at Array.forEach (<anonymous>)
at r (VM186 react-dom.min.js:15)
This is a reference to these lines:
handleChange(event) {
this.setState({ [evt.target.name]: evt.target.value });
}
You have to decide what to call this variable: evt or event.
After I fix that, the next error I get is:
VM385 react-dom.min.js:14 Uncaught TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.
at RecipeBox.handleSubmit (VM187 pen.js:151)
at Object.r (VM186 react-dom.min.js:14)
at a (VM186 react-dom.min.js:12)
at Object.s [as executeDispatchesInOrder] (VM186 react-dom.min.js:12)
at f (VM186 react-dom.min.js:12)
at m (VM186 react-dom.min.js:12)
at Array.forEach (<anonymous>)
at r (VM186 react-dom.min.js:15)
at Object.processEventQueue (VM186 react-dom.min.js:12)
at r (VM186 react-dom.min.js:14)
When I look in RecipeBox.handleSubmit I see:
handleSubmit(event) {
this.state.count++;
var counter = 0;
alert(
"A name was submitted: " +
event.target.food.value +
event.target.ingredients.value
);
this.state.foodArray.push(event.target.food.value);
this.state.ingredArray.push(event.target.ingredients.value);
localStorage.setItem("text", JSON.stringify(this.state.foodArray));
localStorage.setItem("text2", JSON.stringify(this.state.ingredArray));
this.state.div.appendChild(event.target.food.value);
}
Horror of horrors! Repeat after me: We must never, never change state directly unless we are in the constructor. Never. Repeat this 100 times while beating yourself with a stick so you don’t forget. If we were in the constructor, we could do things like this.state.count++;
but anywhere else, it has to be (***HAS TO BE!!!***) done with this.setState. The way to do this is:
this.setState({ counter: this.state.counter + 1});
But you do this several times in this function so you can combine them all in one.
Then the line causing this last error:
this.state.div.appendChild(event.target.food.value);
Again, you never change state directly, but worse, you seem to be trying to do some jQuery-esque DOM manipulation here. But this is React - you don’t need to (and shouldn’t) be manipulating the DOM.
Looking back at your constructor, I see lines like:
var btn = document.createElement("BUTTON"); // Create a <button> element
var t = document.createTextNode(this.state.localStorageArray[y]);
You are missing the point of React. In React, you teach React how you want to reflect your state data (with JSX and helper functions) and then React handles the DOM.
So, you have a state array of this.state.foodArray. Then inside my JSX I would ahve something like
<div>
<p>
{this.state.foodArray.map(food => (<button>{food}</button>))}
</p>
</div>
This will put all those buttons in there. How does it know when to update it? Because it checks everytime you change this.state with the setState function. This is the magic of React.
All of your DOM elements should be in your JSX, or in a rendering function inside your JSX or called from your JSX.
I haven’t had time to check this function out, just doing it off the top of my head, but it gives you the idea.
Just a quick look through your code in the constructor:
for (var x in text1) {
this.state.localStorageArray.push(text1[x]);
}
Why are you pushing them onto an empty array? Why not just copy the whole thing? Or, you can do it in the initial constructor:
localStorageArray: JSON.parse(localStorage.getItem("text")),
when you define state originally.
I’m not even sure why you’re keeping a separate array for local storage. I see too many calls to local storage. To me, you should only read it once, for example in the constructor. It should be put into your state array for that variable. There is no need to get it again. And the only time you need to write to local storage is when you change the variable. You just stringify the recipe array and save it.
For that matter, I’d rethink how you’re storing the recipe. First of all, choose better variable names than text - variables should tell you what it is. If I were building this, I would have an array called this.state.recipes. Each of those recipes would be an object, like { name: "apple pie", ingredients: "flour, apples, sugar" }
. So, this.state.recipes is an array of those objects. Then when I save those to local storage, I’d have a better key name, something like “gphalenrecipeapp”. If I look at local storage (which you can do in the dev tools, under “application”), you know exactly what it is.
There is a lot of information. I’m sure more problems will arise (they did for me when I was where you are!) but this should get you started.
Please let us know if you need clarification on any of this.