Search code examples
javascriptreactjsreduxreact-reduxnormalizr

What's the best way to deal with a normalized response?


I'm using normalizr to normalize a response.

My problem is that I don't know how to manage the normalized response.

{
  result:[]
  entities: {
    words: {
      //...
      1: {
       definitions: [1, 2, 3]
      }
      // other word objects...      
    },
    definitions: {

      1: 'blah blah'
      2: 'blah blah'
      3: 'blah blah'
      // definition objects
    }
  }
}

I want to pass the words to a react component with definitions. How can I retrieve the words with nested definitions and render it to my component.


Solution

  • webpackbin DEMO

    assuming that your state looks something like this

    entities: {
        words: {
            //...
            1: {
                id:1,
                text:"Word",
                definitions: [1, 2, 3]
            },
            // other word objects...
        },
        definitions: {
            1: {id:1, text:'blah blah'},
            2: {id:2, text:'blah blah'},
            3: {id:3, text:'blah blah'},
            // definition objects
        }
    },
    wordsById : [1,4,7,8,22]
    

    then... WordList may looks like this. Slice ids of words from state, in order to render list

    const WordList = ({ids}) => <div>{ids.map(id => <Word id={id} key={id}/>)}</div>;
    
    export default connect(state =>({ ids:state.wordsById }))(WordList);
    

    and Word component: Get particular word from state by id from props, calculate definitions list through map

    const Word = ({word, definitions}) =>(
        <div className="word-block">
            <span>{word.text}</span>
            <DefinitionsList definitions={definitions}/>
        </div>
    )
    
    const mapStateToProps = (state, props) =>{
        const word = state.entities.words[props.id];
        const { definitions:ids } = word
        return {
            word,
            definitions:ids.map(id => state.entities.definitions[id])
        };
    }
    
    export default connect(mapStateToProps, actions)(Word);
    

    and DefinitionsList

    const DefinitionsList = ({definitions})=> (
        <div className="definitions">
            {definitions.map(def =><div key={def.id}>{def.text}</div>)}
        </div>
    );
    

    Functional compontent was used just for short.