Bogdan Slovyagin Bogdan Slovyagin - 15 days ago 5
React JSX Question

How to normalize an array of objects in the flattest way for the Redux?

Let’s say I have JSON response from server which is an array of nested objects. How to flatten it out making store handling as easy as possible? I’ve tried to use a normalizr tool like this:

const imageSchema = new Schema('image', { idAttribute: 'id' });
const tooltipSchema = new Schema('tooltips', { idAttribute: 'id' });
imageSchema.define({
tooltips: arrayOf(tooltipSchema),
});
const initData = data.map(item => normalize(item, imageSchema));


But I believe I’m doing it wrong because it doesn’t help much. The store is still too complex and therefore I need to use some recursive stuff in reducer to update the state.

Moreover, a deeply nested state makes working with react-redux
connect()
very hard too, because it does only a shallow comparison.

The shape of a reponse be like:

[
{
"id": 1,
"title": "Partridge",
"tooltips": [
{
"id": 10,
"x": 0.56,
"y": 0.59,
"content": "Jacky"
},
{
"id": 11,
"x": 0.08,
"y": 0.8,
"content": "Sarah"
}
]
},
{
"id": 2,
"title": "The Great Seal of South Australia",
"tooltips": [
{
"id": 20,
"x": 0.77,
"y": 0.74,
"content": "A sheaf of wheat"
},
{
"id": 21,
"x": 0.16,
"y": 0.2,
"content": "A sheep"
}
]
}
]

Answer

Based on your sample here, It seems like you're trying to modify the state (hence the reason you're having trouble because of redux's shallow comparison). State should be regarded as immutable and everything returned in your reducers should be completely new objects. Object.assign modifies the first argument.

Try replacing return Object.assign(state, { data: newEntities })

with return Object.assign({}, state, { data: newEntities })

If you stick with this, flat data structure is not needed.