score:1

Accepted answer

Here is your edited CopePen and here is the main code that I modified :

TodoList.js :

import { makeStyles, List } from "@material-ui/core";
import React from "react";
import { useSelector } from "react-redux";
import TodoItem from "./TodoItem";

const useStyles = makeStyles({
  rootDiv: {
    display: "flex",
    flexDirection: "column",
    justifyContent: "center",
    marginLeft: "10px",
    marginRight: "10px"
  },
  p: {
    fontSize: "30px",
    fontweight: "bolder"
  }
});

export default function TodoList() {
  const classes = useStyles();
  const todos = useSelector((state) => state.TodoReducer);
  const filter = useSelector((state) => state.viewFilterReducer);

  const getVisibleTodos = (todos, filter) => {
    switch (filter) {
      case "SHOW_ALL":
        return todos;
      case "SHOW_ACTIVE":
        return todos.filter((todo) => !todo.done);
      case "SHOW_COMPLETED":
        return todos.filter((todo) => todo.done);
      default:
        return todos;
    }
  };
  const visibleTodos = getVisibleTodos(todos, filter);

  return (
    <div className={classes.rootDiv}>
      {visibleTodos?.length === 0 ? (
        <p className={classes.p}>No Todo Item Here</p>
      ) : (
        <List>
          {/*
            I moved the list here, because you need to create only one list 
            and loop over you items  
          */}
          {visibleTodos.map((todo, i) => (
            <TodoItem key={i} todo={todo} />
          ))}
        </List>
      )}
    </div>
  );
}

TodoItem.js :

import React, { useState } from "react";
import { useDispatch } from "react-redux";
import { todoDeleted, todoUpdated, todoCompleted } from "../Slices/TodoSlice";
import {
  Button,
  Checkbox,
  List,
  ListItem,
  ListItemSecondaryAction,
  ListItemText,
  ListItemIcon,
  makeStyles
} from "@material-ui/core";

/* 
Since we fixed the issue about displaying multiple <List>,
you only need to style the items.
You can now properly define the height of your items, and set whatever you want as style,
the default flex layout is kept
*/
const useStyles = makeStyles({
  item: {
    height: "35px",
    alignItems: "center",
    backgroundColor: "#fce4ec",
    border: "1px solid #aaaaaa",
    borderRadius: "20px",
    margin: "5px 5px"
  }
});

export default function TodoItem({ todo, i }) {
  const classes = useStyles();
  const dispatch = useDispatch();
  const [edit, setEdit] = useState(false);
  const [text, setText] = useState(todo.text);

  const handleUpdate = () => {
    dispatch(
      todoUpdated({
        id: todo.id,
        text
      })
    );

    if (edit) {
      setText(todo.text);
    }
    setEdit(!edit);
  };

  return (
    <ListItem className={classes.item}>
      <Checkbox
        value={todo.id}
        onChange={(e) => dispatch(todoCompleted(+e.target.value))}
        defaultChecked={todo.done}
      />
      <ListItemText>
        {todo.done ? (
          <p>
            <del>{todo.text}</del>
          </p>
        ) : (
          <h4>
            {edit ? (
              <input
                type="text"
                placeholder={text}
                value={text}
                onChange={(e) => setText(e.target.value)}
              />
            ) : (
              todo.text
            )}
          </h4>
        )}
      </ListItemText>
      <ListItemSecondaryAction>
        <button
          variant="contained"
          color="primary"
          edge="end"
          onClick={() => handleUpdate()}
          disabled={todo.done}
        >
          {edit ? "Update" : "Edit"}
        </button>
        <button
          variant="contained"
          color="primary"
          onClick={() => dispatch(todoDeleted(todo.id))}
        >
          Delete
        </button>
      </ListItemSecondaryAction>
    </ListItem>
  );
}

I mainly changed the following things :

  1. Moved the <List> component in the parent. You were creating a list for each item, which were creating multiple CSS problems. Pay attention to what your component is supposed to display !
  2. Removed the CSS listRoot and the div node as well. It's not needed anymore
  3. Moved the checkbox as the first child of the listItem so it respect the order you asked for

The layout has its own padding value. I can only HIGHLY advice you to keep it as it is since it's clean, but if you really want to center your items'content, you can still add paddings to you list items and second element, something like :

const useStyles = makeStyles({
  item: {
    // ...
  },
  itemSpacing: { padding: 0 25% }
});

And then:

<ListItem className={[classes.item, classes.itemSpacing]}>

and :

<ListItemSecondaryAction className={classes.itemSpacing}>

But be really carefull, it will break if your item text is too long, 1) because you set a hard coded height to the item, and 2) because ListItemSecondaryAction is in position: absolute

score:0

It might help if you'll add the css file - therefore we can check the current status.

But anyway, have a look at CSS grid layout. This could be the right thing for you. With CSS grid layout your able to assign an grid position to an element for e.g. checkbox 1. Then you can select with display: grid that id 1 should be displayed first and so on.


Related Query

More Query from same tag