Henry
Henry

Reputation: 195

State Changes but child component didn't re-render

I have new to web development and is trying to learn react and redux.

I am following this tutorial https://www.youtube.com/playlist?list=PLC3y8-rFHvwheJHvseC3I0HuYI2f46oAK

As I'm trying to extend what I learned, I'm trying to list all the users (clickable), once clicked will display (expand/collapse) all the post of the user (clickable again), once post is clicked, will display (expand/collapse) all the comment on that post

APIs to use:

users: https://jsonplaceholder.typicode.com/users

posts: https://jsonplaceholder.typicode.com/posts?userId={user.id}

comments: https://jsonplaceholder.typicode.com/comments?postId={post.id}

I have added a property collapse, on the users array upon fetch for expand/collapse monitoring

My problems are:

  1. On my UsersContainer component upon click on the user, the collapse property changes (see on console), however the SampleContainer component didn't hide/show
  2. On the tutorial, he said that to change the state we should/must use the action/reducer (forgot the timestamp). Since this is additional property on the array is it ok if I update state on the handleClick function? If no, please give me idea on how to implement this kind of action/reducer.

below is my UserContainer.js

import React, { useEffect } from "react";
import { connect } from "react-redux";

import { fetchUsers } from "../redux";

function UsersContainer({ userData, fetchUsers }) {
  useEffect(() => {
    fetchUsers();
  }, []);

  const handleClick = event => {
    //console.log(userData.users)
    const indx = userData.users.findIndex(obj => obj.id == event.target.value);
    //console.log(indx)
    userData.users[indx].collapse = !userData.users[indx].collapse;
    console.log(userData.users[indx].collapse + " " + indx);
  };

  return userData.loading ? (
    <h2>loading</h2>
  ) : userData.error ? (
    <h2>{userData.error}</h2>
  ) : (
    <div>
      <h2>User List</h2>
      <div className="list-group">
        {userData.users.map(user => (
          <div>
            <button
              type="button"
              className="list-group-item list-group-item-action"
              key={user.id}
              onClick={handleClick}
              value={user.id}
            >
              {user.name}
            </button>
            {/* for update to change SampleContainer component to POST component */}
            {user.collapse && <SampleContainer id={user.id} name={user.name} />}
          </div>
        ))}
      </div>
    </div>
  );
}

const mapStateToProps = state => {
  return {
    userData: state.user
  };
};

const mapDispatchToProps = dispatch => {
  return {
    fetchUsers: () => dispatch(fetchUsers())
  };
};

const SampleContainer = props => {
  return (
    <div>
      {/* trying to pass the id/name in prep for POST component*/}
      display Posts of - {props.name} ({props.id}){" "}
    </div>
  );
};

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(UsersContainer);

here is the codesandbox link: https://codesandbox.io/s/react-redux-testing-mi6ms

Upvotes: 0

Views: 76

Answers (1)

fayeed
fayeed

Reputation: 2485

You are directly updating the userData props which are immutable i.e is they cannot change and don't update the UI. You will need to update your redux store by dispatching a new action, in this case, it would be UPDATE_USER_STATUS.

Here's a codesandbox with a working example.

Upvotes: 1

Related Questions