Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a React render condition for 3 options

how to create a rendering condition for 3 options? The ternary operator is insufficient for this option and the code I wrote in my opinion is not quite ok.

import React, { useEffect } from "react";
import { useParams } from "react-router-dom";
import { useSelector } from "react-redux";
import { useDispatch } from "react-redux";
import { getTodoItems, setUrlParams } from "../redux/todoSlice";

import TodoItem from "./TodoItem";

const TodoList = ({ filter }) => {
  const { id } = useParams();
  const dispatch = useDispatch();
  const { searchTerm, todoList } = useSelector((state) => state.todo);

  useEffect(() => {
    dispatch(getTodoItems(id));
    dispatch(setUrlParams(+id));
  }, [dispatch, id]);

  const searchedItems = todoList?.filter((todo) => {
    if (!searchTerm) {
      return todo;
    } else {
      return todo?.title.toLowerCase().includes(searchTerm);
    }
  });

  // FROM HERE
  const filteredItems = (filter) => {
    if (filter === "all") {
      return searchedItems?.map((todo, id) => (
        <TodoItem key={id} data={todo} />
      ));
    } else if (filter === "active") {
      return searchedItems
        ?.filter((todo) => !todo.isCompleted)
        .map((todo, id) => <TodoItem key={id} data={todo} />);
    } else if (filter === "done") {
      return searchedItems
        ?.filter((todo) => todo.isCompleted)
        .map((todo, id) => <TodoItem key={id} data={todo} />);
    }
  };

  return (
    <div>
      {filter === "all" && filteredItems("all")}
      {filter === "active" && filteredItems("active")}
      {filter === "done" && filteredItems("done")}
    </div>
  );
};

export default TodoList;

Can you please tell me how to make the code more efficient and simpler?

like image 409
TheDareback Avatar asked Oct 22 '25 04:10

TheDareback


2 Answers

You can use Object literal functionality here. You can define your filteredItems as an object and render them with the type.

const filteredItems = (filter) => {
  return {
    all: searchedItems?.map((todo, id) => <TodoItem key={id} data={todo} />),
    active: searchedItems
      ?.filter((todo) => !todo.completed)
      .map((todo, id) => <TodoItem key={id} data={todo} />),
    done: searchedItems
      ?.filter((todo) => todo.completed)
      .map((todo, id) => <TodoItem key={id} data={todo} />),
  }[filter];
};
return (
  <div>
    {filterRender(filter)}
  </div>
);

like image 120
mc-user Avatar answered Oct 23 '25 18:10

mc-user


I think that the main problem here is the conditional redundancy, you are doing the same validation two times, I would remove all the if conditions from filteredItems and move each returned TodoItem into his own function, like this:

const TodoList = ({ filter }) => {
  const { id } = useParams()
  const dispatch = useDispatch()
  const { searchTerm, todoList } = useSelector(state => state.todo)

  useEffect(() => {
    dispatch(getTodoItems(id))
    dispatch(setUrlParams(+id))
  }, [dispatch, id])

  const searchedItems = todoList?.filter(todo => {
    if (!searchTerm) {
      return todo
    } else {
      return todo?.title.toLowerCase().includes(searchTerm)
    }
  })

  const AllItems = () => {
    return searchedItems?.map((todo, id) => <TodoItem key={id} data={todo} />)
  }

  const activeItems = () => {
    return searchedItems
      ?.filter(todo => !todo.isCompleted)
      .map((todo, id) => <TodoItem key={id} data={todo} />)
  }

  const doneItems = () => {
    return searchedItems
      ?.filter(todo => todo.isCompleted)
      .map((todo, id) => <TodoItem key={id} data={todo} />)
  }

  return (
    <div>
      {filter === 'all' && AllItems()}
      {filter === 'active' && activeItems()}
      {filter === 'done' && doneItems()}
    </div>
  )
}
like image 30
Yago Biermann Avatar answered Oct 23 '25 20:10

Yago Biermann