This is my delete code, it works only on first invokation?
const byId = (state = {}, action) => {
switch (action.type) {
case 'REMOVE_TODO':
return Object.keys(state).filter( key => {
return state[key].id !== action.id
}).reduce((acc,key) => Object.defineProperty(acc, key, {
value: state[key], }),{});
default:
return state;
}
};
My state object is like this:
{"abcd1": {id: "abcd1", text: "hello world"}, "efgh2": {id: "efgh2", text: "hello there"}
So what happens is I can delete on the first invokation, then my object becomes all empty when I try to invoke again? or only {} . Can't figure out why?
Well I would prefer to shape my state object like:
[{id: "abcd1", text: "hello world"},{id: "efgh2", text: "hello there"}]
since it's just redundant to repeat the object key and the todo id if they are the same.
Then, in the reducer you can have something like:
const byId = (state = [], action) => {
switch (action.type) {
case 'REMOVE_TODO':
return state.filter((todo) => todo.id != action.id)
default:
return state;
};
Related
Struggling to figure out how to add a new item to an object from my reducer. This is the payload I am receiving GH
This is the relevant code in my reducer
const initialForm = {
nationality: '',
}
function addName(state= initialForm, action) {
switch(action.type){
case ADD_NEW_NATIONALITY:
console.log('nationality',action.payload.name)
return {
...state,
[action.payload.nationality]: action.payload.value
}
default:
return state
}
}
and my action creators
export const addFullName = newName => dispatch => {
console.log(newName)
axios.get(`https://api.nationalize.io?name=${newName.name}`)
.then(res => {
dispatch({ type: ADD_NEW_NATIONALITY, payload: res.data.country[0].country_id})
})
Please help me figure this out
Your payload is just a plain value (not an object), so you cannot find action.payload.name and action.payload.value
And similarly, you cannot find action.payload.nationality either.
Here is how your action looks like
{ type: ADD_NEW_NATIONALITY, payload: 1} //`1` is country_id
To set nationality correctly, you can check the below implementation
const initialForm = {
nationality: '',
}
function addName(state= initialForm, action) {
switch(action.type){
case ADD_NEW_NATIONALITY:
return {
...state,
nationality: action.payload //update your `nationality` property with a plain value from `payload`
}
default:
return state
}
}
I build an app in React with Redux and in my state I have a list of objects and I want to update one object from that list by unique id.
My object looks like:
{
id: '',
title: '',
description: '',
label: '',
}
My state:
const initialState = {
compare: dayjs().month(),
savedEvents: [],
}
When I push a new event in that list I use:
case 'events/setNewEvent':
return { ...state, savedEvents: [...state.savedEvents, action.payload] };
My problem is that I don't know to write the right code to update just one object by id sent from my form.
You can use combination of Array method map and spread operator
function updateOne(array, obj) {
return array.map((item) => {
if (obj.id === item.id) {
// update whatever you want
return {...item, title: obj.title };
} else {
return item;
}
})
}
reducer:
case 'events/setNewEvent':
return {
...state,
savedEvents: updateOne(state.savedEvents, action.payload)
};
I am trying to use redux to add key value pairs to my store. However, Im not sure how to accomplish this. In short, i am retrieving data from firebase, I want to add that data to my redux store, but I have to do it one item at a time. My desired structure of my state object is something like this:
reminders
- reminder key 1
- reminder title
- reminder date 1
- reminder key 2
- reminder title
- reminder date 1
and so on.
But I cant figure out how to add children to my state.reminders object
Here is my action:
const fetchReminders = (uid) => async dispatch => {
firebaseReminders.child(uid).orderByChild("date").on("value", snapshot => {
snapshot.forEach(function(child) {
console.log(child.val())
dispatch({
type: 'fetchReminders',
value: child.val(),
key: child.key
});
})
});
};
so this would dispatch the action for every single item that I retrieve from the database, and then in my reducer I want to add that item to the state tree using action.key as the key. Currently I have
const remindersReducer = (state = initialState, action) => {
switch(action.type) {
case "fetchReminders":
return Object.assign({}, state, {
reminders: action.value
});
default: return state;
}
};
which is not correct. How can I add a child node to my state.reminders object with the key of action.key, and the value of action.value
let initialState = {
reminders: {}
}
const remindersReducer = (state = initialState, action) => {
switch(action.type) {
case "fetchReminders":
return Object.assign({}, state, {
reminders: {
...state.reminders,
[action.key]: action.value
}
});
default: return state;
}
};
let state1 = remindersReducer(initialState, {
type: 'fetchReminders',
key: 'reminderKey1',
value: 'reminderValue1'
});
console.log(state1)
let state2 = remindersReducer(state1, {
type: 'fetchReminders',
key: 'reminderKey2',
value: 'reminderValue2'
});
console.log(state2)
let state3 = remindersReducer(state2, {
type: 'fetchReminders',
key: 'reminderKey3',
value: 'reminderValue3'
});
console.log(state3)
The snippet should help you achieve what you want to do.
You can assign an object as the key of action.key by using the following format:
{
[action.key]: action.value
}
Its called Computed Property Names.
Starting with ECMAScript 2015, the object initializer syntax also
supports computed property names. That allows you to put an expression
in brackets [], that will be computed and used as the property name.
Source
I'm trying some app in react redux and i have a problem with updating (push, remove, update) the nested array in state.
I have some object called service like this:
{
name: 'xzy',
properties: [
{ id: 1, sName: 'xxx'},
{ id: 2, sName: 'zzz'},
]
}
Whatever I did (in case of adding property to collection) in the reducer with the properties collection generate problem that all properties got same values as the last I had recently added -> Added property object is in service properties collection but the action replace all values in all properties in this collection.
My reducer:
export function service(state = {}, action) {
switch (action.type) {
case 'ADD_NEW_PROPERTY':
console.log(action.property) // correct new property
const service = {
...state, properties: [
...state.properties, action.property
]
}
console.log(service); // new property is pushed in collection but all properties get same values
return service
default:
return state;
}
}
I have tried some solution with immutability-helper library and it generate the same problem:
export function service(state = {}, action) {
case 'ADD_NEW_PROPERTY':
return update(state, {properties: {$push: [action.property]}})
default:
return state;
}
For example when I add new property { id: 1, sName: 'NEW'} to example above I will get this state:
{
name: 'xzy',
properties: [
{ id: 1, sName: 'NEW'},
{ id: 1, sName: 'NEW'},
{ id: 1, sName: 'NEW'}
]
}
Can someone help? :)
Make a copy of action.property as well. Whatever is dispatching this action, it could be reusing the same object.
export function service(state = {}, action) {
switch (action.type) {
case 'ADD_NEW_PROPERTY':
console.log(action.property) // correct new property
const service = {
...state,
properties: [
...state.properties,
{ ...action.property }
]
}
console.log(service); // new property is pushed in collection but all properties get same values
return service
default:
return state;
}
}
I'd recommend you to use Immutable data https://facebook.github.io/immutable-js/docs/#/List
import { fromJS, List } from 'immutable';
const initialState = fromJS({
propeties: List([{ id: 1, sName: 'xyz' }]
}
function reducer(state = initialState, action) {
case ADD_NEW_PROPERTY:
return state
.update('properties', list => list.push(action.property));
// ...
}
Your service reducer should probably look somewhat like this:
// Copy the state, because we're not allowed to overwrite the original argument
const service = { ...state };
service.properties.append(action.property)
return service
You should always copy the state before returning it.
export default function(state = {}, action) {
switch(action.type) {
case 'GET_DATA_RECEIVE_COMPLETE': {
const data = action.firebaseData;
const newState = Object.assign({}, state, {
data
});
return newState
}
default:
return state;
}
}
In my application i am displaying person data.
I have a scenario where I can input new person. So far I have got this:
Reducer:
export default function (state = [], action) {
console.log("Reducing");
switch (action.type) {
case 'ADD':
console.log("ADDING!");
return action.payload;
break;
}
return state;
}
Action:
export const addPerson = (person) => {
console.log("addPerson Action Fired! ", person);
return {
type: 'ADD',
payload: person
}
};
I have a reducer with few person data which i am showing in my application but i am blocked at this point of adding new person. So far i can see my input in console log but can't figure out how can i add it to the state.
Help would be very much appreciated.
This is the reducer where i am showing the data from.
export default function () {
return ["abc","def","ghi","jkl"]
}
Now i am displaying a list of these elements from the array(each are one person). When i add one it will be added with these persons and show me the updated list.
You should do the following in your reducer:
export default function (state = [], action) {
console.log("Reducing");
switch (action.type) {
case 'ADD':
return [
...state,
action.payload,
]
}
return state;
}
In this way, you add the person to your existing array. Otherwise you changes your current state value from an array to an object.
Let's consider your person object value is the following and you dispatch it:
{
type: 'ADD',
payload: {
id: 1,
name: 'John Doe',
}
}
With your previous code, you would have the current value:
// First step
return action.payload;
// Second step
return { id: 1, name: 'John Doe' };
With the corrected code:
// First step
return [
...state,
action.payload,
]
// Second step
return [
...[],
{ id: 1, name: 'John Doe' },
]
// Third step
return [{ id: 1, name: 'John Doe' }];