Some Tips
- Avoid using constructor.
- Avoid using
.bind(this)
- Destructuring will help you to make cleaner code.
Questions
- Avoid initializing the state empty state in the constructor. However, I had to initialize shoppingCart: [] in componentDidMount hook to avoid type error. What is the better and cleaner approach?
You can have 2 aproaches to this
There is a way to avoid this, what you do is destruct the state in the variables you want and set then a default value of an array.
state = {}
render() {
const {
shoppingCart = []
} = this.state
...
}
This way you don't need to check if shoppingCart
is an array, and you only need to declare this.state
as an object ( it can be just an empty object ).
You can also do
render() {
const {
shoppingCart = []
} = this.state || {}
...
}
And now you don't even need state = {}
Because you are using arrow functions, you don't need .bind(this)
and also you can avoid de constructor and just use
state = {
...
}
This way you can declare shoppingCart
and items
and don't need to declare it in componentDidMount
(wich is much better to understand) and now don't need to destruct the state.
state = {
shoppingCart = [],
items = []
}
This way is good if the data you will get is always an array (or the type you specify) and another good reason to use this is that when other programmer look at the code, they will immediately know what is stored in that component state, but when you have too many things in the state, it can get confused.
This aproaches will solve some problems like using ternary to check if you have an state and then return the mapping or if you don't have, return an empty array.
render() {
const {
items = [],
shoppingCart = []
} = this.state
let aisleList = items.map((item, index) => {
return (
<div key={index}>
<span>{item}</span>
<input
type="checkbox"
id={index}
value={item}
onClick={this.handleAileClick}
/>
</div>
);
});
let cartList = shoppingCart.map((item, index) => {
return (
<div key={index}>
<span>{item}</span>
<input
type="checkbox"
autoComplete="off"
value={item}
onClick={this.handleCartClick}
/>
</div>
);
});
...
}
Looking at this, is much clean and easy to understand.
- Is it good practice to keep the logic simple in handleXXXClicks, separation of concern one for handling items and one for shoppingCart?
You can do the way you want, but you need to see what you will do in the future, if both will always do the same, you can create one function for both and just send a different parameter, but if they will do some extra stuff, it's good to have then separated.
*(I'm not english native speaker and maybe I didn't understand exaclty what is this part about).
- I feel aisleList and cartList bloated and I could have written itemComponent which is avoidable duplicate code.
Yes, they look so similar that you should create a component for both and pass the diference in props.
- Is there any better way to handle the item in setState? I couldn't think of using prevState in my scenario.
Here is simple setState
using a function with prevState
. Note that the way you are doing it, you need to have event.persist()
, for more info look here
handleCartClick = event => {
event.persist();
this.setState(prevState => {
return {
items: [...prevState.items, event.target.value],
shoppingCart: prevState.shoppingCart.filter(item => {
return item !== event.target.value;
})
};
});
};
Overall
Your code looks ok, there is only one strange thing. You are using checkboxes and when you click, some get marked and other don't. I don't know if that was a test or you also wanted to solve the checkbox problem. Let me know and I can see what I can do.
I recommend you to start using some new things like I mentioned in the tips part, that help you alot and make your code cleaner.
Also have a look at hooks.
For me, using hooks makes alot of things easier, but also, the code looks cleaner.
I made a demo for you to test and see the new code. I changed some things.
- I changed
handleCartClick
but left handleAileClick
the way it was before, so you can try useing prevState
yourself.
- And also left the part of
itemComponent
for you.
The best way to learn, is doing it!
Hope I helped you!