bananaoomarang / isomorphic-redux

Isomorphic Redux demo, with routing and async actions
https://medium.com/@bananaoomarang/handcrafting-an-isomorphic-redux-application-with-love-40ada4468af4
MIT License
455 stars 87 forks source link

Handling custom complex object in reducer #63

Closed govind999 closed 7 years ago

govind999 commented 8 years ago

How can i do a complex object like this, i saw it in one of the blogs but it is not working, did you use?

const defaultState= Map({ isLoading : false, error : null, data : List() })

// in the handler function return state.merge({ isLoading: false, error: null, data: List(result.result) })

bananaoomarang commented 8 years ago

For that case specifically you might want something like:

state.set('data', List(result.result))

Also if you have maps in maps you’ll need state.mergeDeep.

Immutable.fromJS might also be of interest here if you haven’t seen it. Though really it’s nicer just to keep objects as immutable through the whole app (unless it’s from a remote, result.result might be?), then you don’t need to keep typing List() or fromJS (sometimes it can get confusing what is Immutable and what’s not).

govind999 commented 8 years ago

basically my api returns different array of objects and i want to send that to UI, so when i change the code like you mentioned, do i need to change any other thing in the UI in your boilerplate code?

is this still going to work?

export default connect(state => ({ products: state.search.products }))(Home)

bananaoomarang commented 8 years ago

Cool cool.

I can’t tell without more code whether that will work, it depends what part of state that Reducer maps onto. Maybe the array is at state.search.products.data? If so that should work.

The important thing is that the reference to the selected part of state changes, otherwise connect won’t pass in new props and trigger a rerender. This means that if that Reducer modifies state.search.products this will work, otherwise I will need a more detailed look.

Hope that helps!

govind999 commented 8 years ago

Thanks for your reply. My object looks as below

const defaultState = Map({
  isFetching:false,
  deparments: List(),
  products:List(),
  breadcrumb:List()
})

case 'GET_GALLERY_DATA':

  //console.log("-- api success handler--");
  //console.log(action);

   var depts = getGalleryParsedData(action.res.data);
   var products = getProducts(action.res.data);
   var breadcrumb = getBreadcrumbs(action.res.data);

   state = state.set('isFetching', true);
   state = state.set('deparments', List(depts))
   state = state.set('products', List(products))
   state = state.set('breadcrumb', List(breadcrumb))

 //console.log("---state----");
 //console.log(state);
  return state;

so the response from API is array of objects, but it is failing while trying to loop

Cannot read property 'map' of undefined

this.props.products.map((product, index) =>

The products is not getting linked, so when i console in reducer i see it as a Map instead of List, do you think that is the problem?

export default connect(state => ({ products: state.search.products }))(Home)

export { default as search } from './SearchReducer';
govind999 commented 8 years ago

we got this working, we need to use

state.search.get("products")