1

My redux state hierarchy

Hello, I am new to redux and I am struggling with a problem. I am trying to access and map over the comments within my post array. However, I am not sure how to do this. So far, I've tried changing the actions and reducers in order to solve this issue. I think the problem is within the react and redux. I can't tell if my mapStateToProps is working correctly. Also, the state is being fetched from my express server and it seems to be working properly as you can see in the picture.

My getPost action:

export const getPost = (group_id, post_id) => async dispatch => {
  try {
    const res = await axios.get(`/api/groups/${group_id}/${post_id}`);

    dispatch({
      type: GET_POST,
      payload: res.data
    });
  } catch (error) {
    dispatch({
      type: POST_ERROR,
      payload: { msg: error.response.statusText, status: error.response.status }
    });
  }
};

The initial state:

const initialState = {
  groups: [],
  group: [],
  loading: true,
  error: {}
};

The reducer:

case GET_POST:
  return {
  ...state,
  post: payload,
  loading: false
};

Where I'm trying to map over the comments:

import React, { Fragment, useEffect } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { getPost } from '../../../redux/actions/group';

const Post = ({ getPost, post, match }) => {
  useEffect(() => {
    getPost(match.params.group_id, match.params.post_id);
  }, [getPost, match.params.group_id, match.params.post_id]);

  // I want to map over the comments here
  return (
      {post.comments.map(comment => ({ comment }))}
  );
};

Post.propTypes = {
  getPost: PropTypes.func.isRequired,
  group: PropTypes.object.isRequired
};

const mapStateToProps = state => ({
  post: state.post
});

export default connect(mapStateToProps, { getPost })(Post);
5
  • 1
    The coments seems to be an array of objects. Can you update the structure of that object and what are trying to display. And FYI we can't display an object. Commented Feb 28, 2020 at 4:31
  • Hello, @Vishnu. I am trying to display the post. The post will have comments replying to it. Basically, I am trying to display all of the comments of the post if you click on the post. Commented Feb 28, 2020 at 4:38
  • 1
    I got that, but the comment is not a string. So if the shape of comment is like {comment: 'foo', author:'bar'} You can iterate over it like {post.comments.map(comment => (<div>comment: {comment.comment} {comment.author}</div> ))}, PS: based on how you want the layout :v Commented Feb 28, 2020 at 4:43
  • @Vishnu I was trying to do it that way before but it gave me TypeError: Cannot read property 'comments' of undefined. I don't think I can access post unless I go through group. Commented Feb 28, 2020 at 4:51
  • 1
    The initialState is missing posts. You can initialize post with {} and add a check in return statement like {post.comments && post.comments.map(.... Commented Feb 28, 2020 at 5:01

1 Answer 1

1

You can access nested object with some tricks using redux, we have use this way in our prod env for some time.

First the reducer (you can make this reducer even more complex)

const LocalStorageReducer = createReducer<Store['localStorage']>(
  new LocalStorage(),
  {
    saveLocalStorageItem(state: LocalStorage, action: any) {
      return {...state, [action.payload.item]: action.payload.value}; // <= here
    },
  }
);

For Actions

export const actions = {
  saveLocalStorageItem: (payload: InputAction) => ({type: 'saveLocalStorageItem', payload}),
};

For the type InputAction

export class InputAction {
  item: string;
  value: string | Array<string> | null | boolean;
  constructor() {
    this.item = '';
    this.value = null;
  }
}

For the handler in component

this.props.saveLocalStorage({ item: 'loading', value: false });

In this way you can go one way done to the nested redux store.
For complex (4-5 levels) and multiple (> 2 times) data structure, there are other ways, but in most situations, it's good enough.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.