reactjsreact-hooksmaterial-ui

Why is my Checkbox (Material-UI) not updating? I am using useState, useEffect, alongside with Checkbox from Material-UI


Why is my checkbox (Material-UI) not updating? I am using useState, useEffect, alongside with Checkbox from Material-UI. This is especially weird because the {isLiked ? <p>liked</p> : <p>not liked</p>} updates properly without any problem but it's just the Checkbox that is not working. I am trying to update the checked status of the Checkbox using the defaultChecked attribute. It worked when I set the isLiked Boolean directly, but once I tried to use useState and useEffect, it just stopped working. Here is my code:

const Post = ({ createdOn, text, username, comments, likedUsers }) => {
    const d = new Date(createdOn);
    const userDetails = useAuthState();

    const [isLiked, setIsLiked] = React.useState(false);
    React.useEffect(() => {
        if (userDetails.user){
            if (likedUsers.indexOf(userDetails.user.user_id) !== -1)
                setIsLiked(true)              
        }
    },[])
    return (
        <>
            <div>
                <h3>{text}</h3>
               
                <div>
                    <span>{d.toLocaleDateString()}</span>&nbsp;<span>{d.toLocaleTimeString()}</span>
                </div>
                <div>{username}</div>
                <div>
                    <FormControlLabel
                        control={
                            <Checkbox
                                icon={<FavoriteBorder />}
                                checkedIcon={<Favorite />}
                                name="checkedH"
                                defaultChecked={isLiked}
                                
                            />}
                    />{likedUsers.length}
                </div>
                <Commentlist comments={comments} />
                {isLiked ? <p>liked</p> : <p>not liked</p>}
                
                <hr />
            </div>
        </>
    )
}

export default Post

Thanks in advance.

Here is a similar code snippet that reproduces the problem without the external dependencies:

import React from "react";
import FormControlLabel from "@material-ui/core/FormControlLabel";
import Checkbox from "@material-ui/core/Checkbox";
import Favorite from "@material-ui/icons/Favorite";
import FavoriteBorder from "@material-ui/icons/FavoriteBorder";

const Post = () => {
  const likedUsers = [1, 2, 3, 4];
  const username = "user1";
  const user = {
    user_id: 1,
    username
  };
  const [isLiked, setIsLiked] = React.useState(false);
  React.useEffect(() => {
    if (user) {
      if (likedUsers.indexOf(user.user_id) !== -1) setIsLiked(true);
    }
  }, []);
  return (
    <>
      <div>
        <div>{user.username}</div>
        <div>
          <FormControlLabel
            control={
              <Checkbox
                icon={<FavoriteBorder />}
                checkedIcon={<Favorite />}
                name="checkedH"
                defaultChecked={isLiked}
              />
            }
          />
          {likedUsers.length}
        </div>
        {isLiked ? <p>liked</p> : <p>not liked</p>}

        <hr />
      </div>
    </>
  );
};

export default Post;

When the page first loads I would compare the current user id to see whether it is in the "likedUsers" array in each post to determine whether the user has liked the post or not, and heart Checkbox would show this initial state. Every time the user clicks the heart, it would send a put request to the backend to toggle the status in the database. The "likedUsers" array is a property of each post being fetched when the page is being loaded and is passed down to the Post component. I still haven't coded the put request part yet though, so it is not shown in the question.


Solution

  • I don't understand why you want the useEffect but you can try this:

    Checkbox needs checked property to being active. And an event handler onChange to do this.

    const handleCheckbox = () => {
        setIsLiked(!isLiked);
      };
    
    <FormControlLabel
                control={
                  <Checkbox
                    icon={<FavoriteBorder />}
                    checkedIcon={<Favorite />}
                    name="checkedH"
                    checked={isLiked}
                    onChange={handleCheckbox}
                  />
                }
              />
    

    Please check the example here