Prakash Chokalingam
Prakash Chokalingam

Reputation: 95

Updating json with lodash

Actually I need to handle mysite frontend fully with json objects(React and lodash).

I am getting the initial data via an ajax call we say,

starred[] //returns empty array from server

and am adding new json when user clicks on star buton it,

starred.push({'id':10,'starred':1});

if the user clicks again the starred should be 0

current_star=_findWhere(starred,{'id':10});
_.set(curren_star,'starred',0);

but when doing console.log

console.log(starred); //returns
[object{'id':10,'starred':0}]

but actually when it is repeated the global json is not updating,while am performing some other operations the json is like,

console.log(starred); //returns
[object{'id':10,'starred':1}]

How to update the global , i want once i changed the json, it should be changed ever.Should I get any idea of suggesting some better frameworks to handle json much easier.

Thanks before!

Upvotes: 6

Views: 2943

Answers (2)

kaicurry
kaicurry

Reputation: 199

Working with arrays is complicated and usually messy. Creating an index with an object is usually much easier. You could try a basic state manager like the following:

// This is your "global" store. Could be in a file called store.js
// lodash/fp not necessary but it's what I always use.
// https://github.com/lodash/lodash/wiki/FP-Guide
import { flow, get, set } from 'lodash/fp'

// Most basic store creator.
function createStore() {
  let state = {}
  return {
    get: path => get(path, state),
    set: (path, value) => { state = set(path, value, state) },
  }
}

// Create a new store instance. Only once per "app".
export const store = createStore()

// STARRED STATE HANDLERS
// Send it an id and get back the path where starred objects will be placed.
// Objects keyed with numbers can get confusing. Creating a string key.
const starPath = id => ['starred', `s_${id}`]
// Send it an id and fieldId and return back path where object will be placed.
const starField = (id, field) => starPath(id).concat(field)

// import to other files as needed
// Add or replace a star entry.
export const addStar = item => store.set(starPath(item.id), item)
// Get a star entry by id.
export const getStar = flow(starPath, store.get)
// Get all stars. Could wrap in _.values() if you want an array returned.
export const getStars = () => store.get('starred')
// Unstar by id. Sets 'starred' field to 0.
export const unStar = id => store.set(starField(id, 'starred'), 0)

// This could be in a different file.
// import { addStar, getStar, getStars } from './store'

console.log('all stars before any entries added:', getStars()) // => undefined

const newItem = { id: 10, starred: 1 }
addStar(newItem)
const star10a = getStar(10)
console.log('return newItem:', newItem === star10a) // => exact match true
console.log('star 10 after unstar:', star10a) // => { id: 10, starred: 1 }
console.log('all stars after new:', getStars())

// Each request of getStar(10) will return same object until it is edited.
const star10b = getStar(10)
console.log('return same object:', star10a === star10b) // => exact match true
console.log('return same object:', newItem === star10b) // => exact match true

unStar(10)
const star10c = getStar(10)
console.log('new object after mutate:', newItem !== star10c) // => no match true
console.log('star 10 after unstar:', getStar(10)) // => { id: 10, starred: 0 }
console.log('all stars after unstar:', getStars())

Upvotes: 3

blade091
blade091

Reputation: 652

I think the problem is in mutating original state. Instead of making push, you need to do the following f.e.:

var state = {
    starred: []
};

//perform push
var newItem = {id:10, starred:1};
state.starred = state.starred.concat(newItem);

console.log(state.starred); 
//{ id: 10, starred: 1 }]

var newStarred = _.extend({}, state.starred);
var curr = _.findWhere(newStarred, {id: 10});

curr.starred = 0;

state = _.extend({}, state, {starred: newStarred});

console.log(state.starred)
//{ id: 10, starred: 0 }]

To solve this in a more nice looking fashion, you need to use either React's immutability helper, or ES6 stuff, like: {...state, {starred: []}} instead of extending new object every time. Or just use react-redux =)

Upvotes: 0

Related Questions