无法在数组中识别组件

IT技术 reactjs material-ui
2021-05-15 13:46:39

我正在尝试动态渲染元素,但是当我尝试从数组中拼接组件时,它不会被删除。

const [cardsInGrid, setCards] = React.useState([]);

const [showReactions, setShowReactions] = React.useState(false);

const onReactionsClick = () => {
    setShowReactions(!showReactions);
  };

useEffect(() => {
    if (showReactions) {
      setCards(cardsInGrid.concat(<Reactions />));
    } else if (!showReactions) {
      console.log(cardsInGrid);
      var index = cardsInGrid.indexOf(<Reactions />);
      console.log(index);
      if (index > -1) {
        setCards(cardsInGrid.splice(index, 1));
        console.log(cardsInGrid);
      }
    }
  }, [showReactions]);

第一个 if 语句中的 concat 有效,但 console.log(index) 每次都返回 -1。是我拥有的一个组件。

编辑:组件数组

const componentList = [
    { id: "tags", component: Tags },
    { id: "reactions", component: Reactions },
    { id: "emojistats", component: EmojiStats },
    { id: "filters", component: Filter },
  ];

如果我有一个预定义的数组,我将如何呈现这些组件?

1个回答

数组::拼接

splice 就地改变数组,但react状态通过返回新对象和数组引用来工作。

数组::过滤器

数组过滤器可以返回您需要的新数组。使用 filter 函数的第二个参数,您可以过滤所有数组元素的索引,这些索引不等于要从数组中删除的元素的索引。

splice()方法通过删除或替换现有元素和/或在适当位置添加新元素来更改数组的内容。

useEffect(() => {
  if (showReactions) {
    setCards(cardsInGrid.concat(<Reactions />));
  } else if (!showReactions) {
    console.log(cardsInGrid);
    var index = cardsInGrid.indexOf(<Reactions />);
    console.log(index);
    if (index > -1) {
      setCards(cardsInGrid.filter((_, i) => i !== index);
      console.log(cardsInGrid);
    }
  }
}, [showReactions]);

编辑:使用组件配置数组

/**
 * External source of truth
 * Could be global variable like this or passed as prop to rendering component
 */
const componentList = [
  { id: "tags", component: Tags },
  { id: "reactions", component: Reactions },
  { id: "emojiStats", component: EmojiStats },
  { id: "filters", component: Filters }
];

export default function App() {
  // cardsInGrid displays current filtered component list
  const [cardsInGrid, setCardsInGrid] = useState(componentList);
  const [showReactions, setShowReactions] = React.useState(false);

  useEffect(() => {
    if (showReactions) {
      // Filter Reactions component out
      setCardsInGrid(componentList.filter(({ id }) => id !== "reactions"));
    } else {
      // Reset to full component list array
      setCardsInGrid(componentList);
    }
  }, [showReactions]);

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>

      <div>
        <button type="button" onClick={() => setShowReactions(r => !r)}>
          {showReactions ? "Hide" : "Show"} Reactions
        </button>
      </div>

      {cardsInGrid.map(({ id, component: Component }) => (
        <Component key={id} />
      ))}
    </div>
  );
}

编辑过滤器组件列表

注意:如果您需要过滤的不仅仅是单个组件,那么通用的解决方案可能是组件配置 ID 的存储映射,用于过滤和使用 array::includes

const [filterBy, setFilterBy] = useState({});

// logic to handle adding/removing filters by name
// i.e. filterBy = { reactions: 'reactions', ...etc }

useEffect(() => {
  const filters = Object.values(filterBy);
  if (filters.length) {
    // Filter components out if id matches anything in filter
    setCardsInGrid(componentList.filter(({ id }) => filters.include(id)));
  } else {
    // Reset to full component list array
    setCardsInGrid(componentList);
  }
}, [filterBy]);