Home > OS >  How to create a React render condition for 3 options
How to create a React render condition for 3 options

Time:05-01

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?

CodePudding user response:

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>
);

CodePudding user response:

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>
  )
}

CodePudding user response:

I'd probably have done something like filter followed by map.

  const filteredItems = (filter) => {
    let filtered = searchedItems;

    if (filter === "active") 
      filtered = searchedItems
        ?.filter((todo) => !todo.isCompleted)
        
    if (filter === "done") 
      filtered =  searchedItems
        ?.filter((todo) => todo.isCompleted)

    return filtered.map((todo, id) => <TodoItem key={id} data={todo} />); 
  };

  return (
    <div>
      {filteredItems(filter)}
    </div>
  );
  • Related