Reactjs 阵列中未识别的组件
我尝试动态渲染元素,但是当我尝试从阵列拼接组件时,它不会被删除Reactjs 阵列中未识别的组件,reactjs,material-ui,Reactjs,Material Ui,我尝试动态渲染元素,但是当我尝试从阵列拼接组件时,它不会被删除 const [cardsInGrid, setCards] = React.useState([]); const [showReactions, setShowReactions] = React.useState(false); const onReactionsClick = () => { setShowReactions(!showReactions); }; useEffect(() =>
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]);
如果我有一个预定义的数组,我将如何呈现这些组件?
splice
在适当的位置变异数组,但react状态通过返回新对象和数组引用来工作
数组筛选器可以返回所需的新数组。使用filter函数的第二个参数,可以过滤所有数组元素的索引,这些索引不等于要从数组中删除的元素的索引
splice()
替换现有图元和/或在适当位置添加新图元
concat
连接两个数组。但是您正在向它传递一个组件。你确定它能工作吗?@Kraylog是的,它确实传递了一个组件并在屏幕上呈现它(尽管没有显示该代码)。你推送的不是
JSX文本吗?记录数组显示它是一个对象数组array::indexOf
也使用严格的相等性,因此只要您推送react组件的新实例,它将永远不会返回-1以外的任何结果。是否有其他值可用于关联数组中的特定元素,如索引?(您可能在某处的数组::map
中渲染这些,对吗?)。也许不把反应
放在数组中,只是有条件地渲染它?@drewrese我希望它动态渲染,因为我希望小部件按特定顺序渲染。我也有其他组件,但顺序很重要,而且最好的执行方法是将这些组件添加到数组中,然后渲染它。然而,如果我在那里放置其他东西而不是组件,我不知道我还将使用什么。你有什么建议吗?在这样的场景中,我会将数组分解为反应前后的内容。另一种模式是使用映射的配置对象数组,其中配置可以是类似{id:'someId',component:Reactions}
,然后使用const index=cardsInGrid.findIndex(el=>el.id==searchId)
。配置中可能有“orderIndex”或“category”属性,您可以使用这些属性来帮助强制执行订单/组织。这不起作用。正如我在第一篇文章中所说的,实际索引返回-1,即使数组中有对象,并且正在添加到数组中。
const componentList = [
{ id: "tags", component: Tags },
{ id: "reactions", component: Reactions },
{ id: "emojistats", component: EmojiStats },
{ id: "filters", component: Filter },
];
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>
);
}
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]);