如何为 3 个选项创建 React 渲染条件

How to create a React render condition for 3 options

如何创建3个选项的渲染条件?三元运算符对于这个选项是不够的,我认为我写的代码不太好。

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;

能否请您告诉我如何使代码更高效、更简单?

我认为这里的主要问题是条件冗余,你做了两次相同的验证,我会从 filteredItems 和将每个返回的 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)
    }
  })

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

您可以在此处使用 Object literal 功能。您可以将 filteredItems 定义为对象并使用类型呈现它们。

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

我可能会做一些像 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>
  );

如果感觉很糟糕,我可能会更清楚地表明我正在过滤数据集,然后发出一些标记作为结果:

  const filteredItems = (filter) => {
    if (filter === "active") 
      return searchedItems
        ?.filter((todo) => !todo.isCompleted) 
    if (filter === "done") 
      return searchedItems
        ?.filter((todo) => todo.isCompleted)
     return searchedItems;
  };

  return (
    <div>
      {filteredItems(filter)?.map((todo, id) => <TodoItem key={id} data={todo} />); }
    </div>
  );