Manipulating State Featuring Fetch

Greetings reader, if you’re a newbie like me in the world of React then you’ve probably stumbled upon the conundrum of adjusting state outside of the parent component.

To start off, let’s get a good understanding of what state is. State in react is essentially;

“The state contains data specific to this component that may change over time. The state is user-defined, and it should be a plain JavaScript object.

If some value isn’t used for rendering or data flow (for example, a timer ID), you don’t have to put it in the state. Such values can be defined as fields on the component instance.”(https://reactjs.org/docs/react-component.html#state)

In other words, state is where you store information that you are planning on manipulating in one way or the other. For example, let’s say you are trying to fetch a bunch of data from an API and use it for your website. The fetch request would be something like this:

state = {
information : []
}
didComponentMount(){
fetch('http://localhost:3000/objs')
.then(resp => resp.json())
.then(data => {
this.setState({
information: data
})
})
}

Your state has been populated with a whole assortment of data.

Now let’s say you had a component that needs to adjust the values within one of your objects that are held in state. The function might look like this:

handleChange = () => {
const newObj = {
hasBigBrain: true
}
const reqObj = {
method: 'PATCH',
headers: {
'Content-Type' : 'application/json'
},
body: JSON.stringify(newObj)
}
fetch('http://localhost:3000/', reqObj)this.props.handleUpdate(Obj)// Assume Obj looks like this {name: Jimmy Neutron, HasBigBrain: false}
(because fetch requests are asynchronous that attribute will still be false when sending information back)
}

Well now you’re probably asking yourself, “hey why is the function handleUpdate have this.props. before it?” Well my young szechuan, that’s because handleUpdate is actually defined inside another component and it was sent down to us. Looking at the parent component it has the function defined:

handleUpdate = (obj) => {
const newInfo = this.state.map(infoObj => {
if(infoObj === obj){
infoObj.hasBigBrain = true
return infoObj
} else {
return infoObj
}
})
this.setState({
information: newInfo
})
}

There’s allot going on here, and it’s worth the time to break down what’s really happening.

  1. We make a new array called newInfo, and we iterate over the entire state.
  2. Each Object within the array is called infoObj, and what we are doing in the first conditional is checking to see if the infoObj is the same thing that was sent up from the child component. Which in this case is obj (aka Jimmy Neutron.)
  3. If infoObj is the same as Obj then we adjust its value of false to true. Then and only then do we return it. If you try to kill two birds with one stone and just return ‘infoObj.hasBigBrain = true’ it will return just ‘true’ and then our array will look like [ obj, obj, obj, true, obj, obj]. You need to first change the value, and then return the object itself.
  4. Then if the other infoObj’s aren’t what we are looking for, we just return the un-manipulated objects. (If you forget this step all of the other objects will be overwritten with ‘undefined’)
  5. Lastly we just setState to the new array and we are good to go!

Yeah this seems like allot of work to just change one value, on one object. Even though a simple refresh can solve all of these problems. But, we are better than that, and we will manipulate data in real-time and give our user the best experience they have ever…….. experienced.

A nice rule of thumb I’d like to think is that if you are changing a value within an object you’ll want to map it out. But, what if you want to delete the object entirely?

Well I got news for you buddy, I have the answer. Lets say in a child component we had this function:

handleDelete = () => {fetch(`http://localhost:3000/objs/${id}`, {method: 'DELETE'})this.props.handleDeletion(Obj)
}

Assume ‘Obj’ is Jimmy Neutron. In our parent component we will have a function defined as.. You guessed it:

handleDeletion = (obj) => {
const newObjs = this.state.toys.filter(infoObj => infoObj !== obj)
this.setState({ information: newObjs})}

Time to break it down now y’all.

  1. The first line is doing allot things, First we creating a new array called newObjs.
  2. Then we are filtering out any object that doesn’t equal the object that we sent down.
  3. Therefore, our array should be one object less than the original state.
  4. Lastly, we are re-setting our state to this new array.

Well now you’re probably asking me, “Well we have our ‘PATCH’, we have our ‘DELETE’, but what about ‘POST’? It’s ok daddies got you. Lets say our component looked something like this:

handleSubmit = (e) => {
e.preventDefault()
const reqObj = {
method: 'POST',
headers: {
'Content-Type' : 'application/json'
},
body: JSON.stringify(this.state)
}
fetch("http://localhost:3000/objs", reqObj)this.props.addNewObj(obj)

You know the drill. Main component will have:

addNewObj = (obj) => {this.setState({information: [...this.state.information, obj]})}

Wam Bam Thank you Ma’am. One last time:

  1. We setState to the original state. We need to sprinkle it in every object by using the ‘…’ otherwise the new state will consist of an array, and then an object after it.

That’s about it folks. You have your full CRUD using react.

An aspiring coder, trying to make sense of The World (of coding.)