How to add new child key-value to a React State object - javascript

I'd like to add a new child key-value to an existing partent -happening on React. Let's say this is my state:
this.state = {
genres: {
Rock: '',
Jazz: '',
Pop: ''
}
}
And this is my method:
addingGenre(tw) {
this.setState({
genres: { [tw]: '', }
})
}
This is obviously not working, itoverwrites my full state --> {genres: tw}.
Thanks so much in advance :)

You need to push to the current state. So it should be something like this:
addingGenre(tw) {
this.setState({
genres: { ...this.state.genres, [tw: '']}
})
}

You can do it like this -
addingGenre(tw) {
const state = this.state;
state.genres[tw] = '';
this.setState(state)
}

Related

rest operator to omit properties

I'm attempting to use the rest operator and restructuring to omit an entry in the object. Based on the documentation, rest should no longer include the key entry 575. After the operation, rest still has the same keys as state. I'm not sure what I'm doing wrong. Thanks in advance.
book = {
id: 575,
title: "Vector Calc"
};
state = {
removedBooks: {
46: {
id: 46,
title: "economics"
},
575: {
id: 575,
title: "Vector Calc"
}
}
};
const {
[book.id]: data, ...rest
} = state;
console.log(rest);
EDIT: I am using React and it is not recommended to mutate the state object directly. Why can't I directly modify a component's state, really? among others
The books are part of the removedBooks property, and are not direct children of the state. You need to destructure the removedBooks property as well.
const book = {"id":575,"title":"Vector Calc"};
const state = {"removedBooks":{"46":{"id":46,"title":"economics"},"575":{"id":575,"title":"Vector Calc"}}};
const { removedBooks: { [book.id]: data, ...removedBooks } } = state;
const newState = { ...state, removedBooks };
console.log(newState);
Your destructuring assignment expects a pattern of { 575: data, ...other... } but state actually has { removedBooks: { 575: data, ...other... } }. Add the removedBooks into your destructuring assignment and it works fine.
book = {
id: 575,
title: "Vector Calc"
};
state = {
removedBooks: {
46: {
id: 46,
title: "economics"
},
575: {
id: 575,
title: "Vector Calc"
}
}
};
const { removedBooks: {
[book.id]: data, ...rest
} } = state;
console.log(rest);

Update 2D state array with 2 different strings

I've been trying to search for this in the docs but couldn't find anything
I'm trying to update my array 'myGamesArray' with the string 'query' and 'image'.
This is a multi-dimensional array and I want to update the first column with 'query' and the second column with 'image'.
I tried this here but it did not work:
constructor(props) {
super(props);
//Initialization of state
//films will contain the array of suggestion
//query will have the input from the autocomplete input
this.state = {
myGamesArray:[{name: "", img: ""}],
games: [],
query: ' ',
image: '',
};
}
this.setState(prevState => {
const { myGamesArray, query, image } = prevState;
return {
myGamesArray: [...myGamesArray[0][0], query.toString()],
myGamesArray: [...myGamesArray[0][1], image.toString()],
query:''
};
},
you should change the myGamesArray once then return it, also spread the prevState so the old values are preserved, so the could should look something like this:
this.setState(prevState => {
const { myGamesArray, query, image } = prevState;
myGamesArray.unshift({
name: query.toString(),
img: image.toString(),
});
return {
...prevState
newGameArray,
query:'',
};
},

How to properly reset Vue Composition Api's reactive values

I'm wondering how should I reset a reactive in vuejs setup? (i know if change it to the ref and using view.value will solve this problem, but there should be an answer to this for using reactive)
setup(props, context){
// states
const DataTable = reactive((null as unknown) as DataTable);
const PolicyForm = reactive((null as unknown) as PolicyForm);
let view = reactive(resetViewState());
let config = reactive(
(resetPreRegisterConfig() as unknown) as PreRegisterConfig
);
// methods:
const fetchProfilelist = (
pagination: Pagination{ page:1, size:15},
sort_label: string = ""
) => {
DataTable.fetchTablelist(api_fetchProfilelist, pagination, sort_label);
};
const pageRefresh = () => {
view = resetViewState(); // 👈
config = resetPreRegisterConfig();
fetchProfilelist();
};
return {
DataTable,
PolicyForm,
view,
config,
fetchProfilelist,
pageRefresh
}
You can use Object.assign:
setup() {
const initialState = {
name: "",
lastName: "",
email: ""
};
const form = reactive({ ...initialState });
function resetForm() {
Object.assign(form, initialState);
}
function setForm() {
Object.assign(form, {
name: "John",
lastName: "Doe",
email: "john#doe.com"
});
}
return { form, setForm, resetForm };
}
See it live on codesandbox
credits: taken from here
Object.assign didn't work for me. (Maybe because I used a shim for the Composition API in Nuxtjs 2?) For anybody that run into the same problem: I had to use a compact loop.
setup() {
const initialState = {
name: "",
lastName: "",
email: ""
};
const form = reactive({ ...initialState });
function resetForm() {
for (const [key, value] of Object.entries(initialState)) {
form[key] = value
}
}
function setForm(values = {name: "John", lastName: "Doe", email: "john#doe.com"}) {
// only loop with the supported keys of initial state
for (const key of Object.keys(initialState)) {
form[key] = values[key]
}
}
return { form, setForm, resetForm };
}
Citing from the official Vueland Discord server:
"For what I know, reactive is the old way we use to do reactivity from the Classic API, so to reset the values should be something like:"
const myData = reactive({
foo: true,
bar: ''
})
function resetValues () {
myData.foo = true
myData.bar = ''
}
Therefore, if you don't change properties you should be able to use Object.assign(). (Correct me if I'm wrong)
How about use ref instead of reactive?
const myData = ref({ xxx: 11 })
// ... After many operations on myData
// resetData
myData.value = { xxx: 11 }
The disadvantage is that you need to add .value when using it in script.
But this is the same as reactive in vue template.
If you have deep objects you can use this trick to reset the values converting them to JSON
setup(){
const form = ref({
order: '',
user:{},
});
const defaultForm = JSON.parse(JSON.stringify(form));
form.value.user = {firstname:"Joe", lastname:"Doe"};
const onSubmit = () => {
// Reset values to default
form.value = JSON.parse(JSON.stringify(defaultForm));
}
}
If you do not want to use ref and want to reset value of a reactive variable then you have to take one key variable for reference in the reactive variable, because reinitializing reactive variable directly will cause to loose reactivity in the process.
So to reset the value use extra key variable in reactive variable, see code as below
setup() {
const initialState = {
name: "",
email: ""
};
const form = reactive({ data: ...initialState });
function resetForm() {
form.data = { ...initialState };
}
function setForm() {
form.data = {
name: "Bahubali",
email: "bahubali#mahismati.com"
});
}
return { form, setForm, resetForm };
}
So basically you are taking data as key of your reactive variable and when you want to reset or set your values you just need to change the form.data and it will be reactive and refreshes the elements which uses form.data.

Copy state object without some fields

I need to transfer state of a component to its parent component, but I don't need to transfer all fields.
What I currently do:
submitHandler = (e) => {
e.preventDefault();
const newState = Object.keys(this.state).map(item => {
if(item !== 'errors')
{
return { item: this.state[item] }
}
});
console.log(newState);
this.props.onChange(newState);
}
Obviously it is not what I need.
state = {
errors: {
fio: '',
email: '',
phone: ''
},
owner: owner.Company,
fio: null,
company: null,
phone: null,
fax: null,
email: null,
adress: null
}
I need to transfer all field except errors. How can I do that?
You can use the rest operator for making it work :)
const { errors, ...newState } = this.state;
this.props.onChange(newState);
I put an example here :) https://repl.it/#EQuimper/PleasantTrimDeclarations
Object destructuring with the rest operator provides a convenient way to copy objects, while omitting specific fields. In the example below, newState will be a copy of this.state, minus the errors property:
submitHandler = e => {
e.preventDefault();
const { errors, ...newState } = this.state;
this.props.onChange(newState);
};

How do I update an array of objects in component state?

I am trying to update the property of an object which is stored in an array.
my state looks something like this:
state = {
todos: [
{
id: '1',
title: 'first item,
completed: false
},
{
id: '2',
title: 'second item,
completed: false
}
],
}
What I am trying to do is access the second element in the 'todos' array and update the completed property to either false -> true or true -> false.
I have a button with the handler for update, and my class method for the update looks like this:
onUpdate = (id) => {
const { todos } = this.state;
let i = todos.findIndex(todo => todo.id === id);
let status = todos[i].completed
let updatedTodo = {
...todos[i],
completed: !status
}
this.setState({
todos: [
...todos.slice(0, i),
updatedTodo,
...todos.slice(i + 1)
]
});
}
While this does work, I want to find out if there is a more concise way of achieving the same result; I tried to use Object.assign(), but that didn't work out because my 'todos' is an array, not an object. Please enlighten me with better code!
It would be best to use update function to make sure you don't work on outdated data:
onUpdate = (id) => {
this.setState(prevState => {
const copy = [...prevState.todos];
const index = copy.findIndex(t => t.id === id);
copy[index].completed = !copy[index].completed;
return { todos: copy }
})
}
You can simply copy your todos from state, then make edits, and after that put it back to the state
onUpdate = (id) => {
var todos = [...this.state.todos]
var target = todos.find(todo => todo.id == id)
if (target) {
target.completed = !target.completed
this.setState({ todos })
}
}

Categories

Resources