How do i save my to-do app's list in local storage? - reactjs

This is what I have so far: https://gist.github.com/justgoof9/f6250cdbd615bda139ef8d56375fa12c
So when I add items to the list then when I refresh the browser, I want it to still save. I want to do it with JSON but don't know how. Can anyone help me?

Yes you can achieve it by using local storage, so whenever you push something to your to Todo list, save the updated list in local storage and then when you are rendering in the UI use the data that is stored in local storage. Here is a small example to achieve this --> https://www.w3schools.com/html/html5_webstorage.asp
Hope this solved your problem.

Hi storing objects in LocalStorage is a bit tricky because LocalStorage accepts strings, but JSON.stringify() comes to the rescue! In you function addToList:
addToList = input => {
let listArray = this.state.lists;
listArray.push(input);
this.setState({
list: listArray,
userInput: ""
});
};
You want to add a LocalStorage call that saves the list from this.state into LocalStorage, like this:
addToList = input => {
let listArray = this.state.lists;
listArray.push(input);
this.setState({
lists: listArray,
userInput: ""
}, () => {
window.localStorage.setItem('savedList', JSON.stringify(this.state.lists));
});
};
And to retrieve it, you need to parse it back into an array/object, like this:
componentDidMount() {
const list = window.localStorage.getItem('savedList');
const parsedList = JSON.parse(list);
this.setState({
lists: parsedList,
})
}
Now every new item you add is saved to localStorage and is retrieved on refresh, all that is left is to apply the same logic to removing items, like this:
listOnClick = index => {
var arr = this.state.lists;
arr.splice(index, 1);
this.setState({ lists: arr }, () => {
window.localStorage.setItem('savedList', JSON.stringify(this.state.lists));
});
};
You also had a typo in addToList, you were assigning to this.state.list instead of this.state.lists

Related

unable to access dynamic object property and store to state in react

I'm trying to grab these arrays from one of the nasa open apis -> https://api.nasa.gov/neo/rest/v1/feed?start_date=START_DATE&end_date=END_DATE&api_key=API_KEY
I have a dynamic date in the params so the objects returned match the date, is there any way I can use my date (even though its a string) and turn it into a 'key' value so I can dynamically grab the objects I need?
like => "2021-08-26" would reference { 2021-08-26: [{},{},{}...] }
I have included my code so far with what I've tried, currently I'm trying to just select all the keys inside the {near_earth_objects} using forEach but I'm still getting an error data.near_earth_objects.forEach is not a function
constructor(){
super();
this.state={
asteroids:[],
time: []
}
}
//grab the current time (year-month-day) and store it in the state
componentWillMount(){
var today = new Date();
var start = today.getFullYear()+'-'+0+(today.getMonth()+1)+'-'+today.getDate();
var end = today.getFullYear()+'-'+0+(today.getMonth()+1)+'-'+(today.getDate()+1);
this.setState({time: [start,end]})
}
componentDidMount(){
fetch(`https://api.nasa.gov/neo/rest/v1/feed?start_date=${this.state.time[0]}&end_date=${this.state.time[1]}&api_key=ipAxYzaENbqRKb7GgzFPcH6QUBsHXY3QKB7uXOf5`
)
.then(response => response.json())
.then((data) => {
let asteroids = []
data.near_earth_objects.forEach((arr)=>{
asteroids.push(arr)
})
this.setState({asteroids:asteroids})
});
}
here is an example of the logged data I'm trying to access
It's important to note that the data is coming back as an object where the values are arrays. Since the return data is an object you cannot iterate over it.
However, to get the data you can Object.values(object) (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/values) to get an array of the values. This will return something that looks like [ [...], [...] ]
After that you can iterate over this information.
In the end your code should look something like this:
Object.values(data.near_earth_objects).forEach((arr)=>{
asteroids.push(...arr)
})

Array empty even after a loop

I'm trying to fill an array with some registers from a database. However, even after retrieving said registers and place them into the array, after the loop the array stays empty
const userParties = [];
userFollowing.forEach(element => {
// Here's when I gather the information that I need
dispatchGetUserEvents(element.user, response => {
userParties.push(response);
console.log(userParties); // Here the array is full of elements, like it's supposed to be
});
});
console.log(userParties); // However, here 'userParties' return '[]'
this.setState({ followUsersEvents: userParties });
this.setState({ userImage: userImg });
I tried to update the state array on the loop, but I had no luck there either.
'userParties' is not a state array btw.
const userParties = [];
userFollowing.forEach(element => {
// Here's when I gather the information that I need
dispatchGetUserEvents(element.user, response => {
userParties.push(response);
console.log('dispatchGetUserEvents', userParties); // Here the array is full of elements, like it's supposed to be
});
});
console.log('outside', userParties); // However, here 'userParties' return '[]'
this.setState({ followUsersEvents: userParties });
this.setState({ userImage: userImg });
run this code and you will see that outside will be printed first and dispatchGetUserEvents later, as I mentioned in comments dispatchGetUserEvents is async function, so first will be executed console.log('outside', ...);

ES6 Add new elements to an array in state

createNewList = (id, input) => {
const foundCard = {...this.state.cards.find(card => id === card.id)};
this.setState(foundCard.list = [...foundCard.list, input]);
};
Hello everyone
There is an array of data (list), which is stored in the state for each object (card).
Problem: I can’t seem to add a new element to this array.
The way it is set up creates only one element and change it every time. But I need to create a new one every time. I tried to create a separate array, add to it using newArray.push (input) and then do this.setState (foundCard.list = [... foundCard.list, ... newArray])`, but have the same result.
I don’t use Redux, because I just started to learn React and I store everything in state yet.
Thanks in advance for your reply.
createNewList = (id, input) => {
const newCards = this.state.cards.map(card => {
if (card.id === id) card.list = [...card.list, input];
return card;
});
this.setState({
cards: newCards
});
};

re-base concat is not a function

(I am using re-base, cant create re-base tag)
I am trying to get user input and then append it onto my state arrays: titles, descriptions and content of a blog and store it in firebase realtime database.
I checked other questions and made sure that my states are arrays so that concat would work.
handleEntry(titleInput, descriptionInput, contentInput) {
this.setState({
titles: this.state.titles.concat(titleInput),
descriptions: this.state.descriptions.concat(descriptionInput),
contents: this.state.contents.concat(contentInput)
})
}
I thought that my state would be updated by instead has a TypeError:this.state.titles.concat is not a function
However, the error points it here at the full stop before syncState:
this.contentsRef = base.syncState('contents', {
context: this,
state: 'contents'
})
UPDATE: I'm not sure if this is the way to do it, but it works. Instead of assigning the state using the state's value, I used a placeholder then assigned it to the state.
handleEntry(titleInput, descriptionInput, contentInput) {
var titleHolder = [...this.state.titles].concat(titleInput);
var descriptionHolder = [...this.state.descriptions].concat(descriptionInput);
var contentHolder = [...this.state.contents].concat(contentInput);
this.setState({
titles: titleHolder,
descriptions: descriptionHolder,
contents: contentHolder
})
}

Mapping over function that sets state in react

I use the function changeCheck to check and uncheck specific components.
When I use the function, it works correctly.
this.props.team is a list of all of the teams.
The goal of changeAllTeams is to be able to check and uncheck all of the teams that have a specific league.
In this example I want to change all of the teams that have a league acronym of NFL:
this.state = {
checked: [],
checkedTeams: [],
teamObject: [],
queryString: [],
accordionStatus: [true, true, true]
}
changeAllTeams = (leagueType) => {
this.props.team.map(
(v, i) => {
if(v.league.acronym === 'NFL'){
this.changeCheck(i, v.team_name, v)
}
}
)
}
componentDidUpdate(){
console.log('checked', this.state.checked)
console.log('team object', this.state.teamObject)
console.log('props team object', this.props.teamObject)
this.props.changeLeagues(this.props.league, this.props.checkedLeagues, this.state.checkedTeams, this.state.queryString, this.state.teamObject, this.state.checked)
}
changeCheck = (index, name, teamObject) => {
//updates checked team state
if(!this.state.checkedTeams.includes(name)){
this.state.checkedTeams[this.state.checkedTeams.length] = name
this.setState({ checkedTeams: [...this.state.checkedTeams] })
//sets team object with new team object
this.state.teamObject[this.state.teamObject.length] = teamObject
this.setState({ teamObject: this.state.teamObject })
} else {
console.log(name)
newChecked = this.state.checkedTeams.filter(v => { return v !== name})
this.setState({ checkedTeams: newChecked })
//removes team object and sets new state
newObjectChecked = this.state.teamObject.filter(v => { return v.team_name !== teamObject.team_name})
this.setState({ teamObject: newObjectChecked })
}
//updates checkbox for specific space
this.state.checked[index] = !this.state.checked[index]
this.setState({ checked: this.state.checked })
this.forceUpdate()
}
When I map over the array in changeAllTeams, only the last object in the array takes effect.
The state for checked updates for everything, but the state for checkedTeams and teamObject does not.
This video may help to understand further:
https://streamable.com/q4mqc
Edit:
This is the structure of the objects in this.props.team:
I don't have your code but I'm pretty sure that the problem is that you didn't provide a unique id for each item (remember that it's most of the time a bad idea to use map index for your items). The thing that you should do is to give each item a unique key and call the function based on that id.
There are a few places where you mutate the contents of this.state. That could cause React to be unable to detect changes in the state because the new and old state are referencing the same object. I would recommend that you don't mutate any state and instead create clones of the data object before passing the new data to setState()

Resources