内部 .map() 样式 "this" Compenent (React.js)
inside .map() style "this" Compenent (React.js)
我已经映射了一组对象,如果单击其中一个元素,我想将该元素的颜色更改为红色(通过添加 CSS class),但它始终是彩色的所有的元素都是红色的。我以为 React 会自动获取上下文?我还需要使用 'this' 吗?
import React, { useState } from "react";
import './Map.css';
const Arr = [
{
id: "i1",
item: "item-1",
},
{
id: "i2",
item: "item-2",
},
{
id: "i3",
item: "item-3",
},
];
const ListElement = (props) => {
return <li className={props.className} onClick={props.onClick}>{props.children}</li>;
};
const Map = () => {
const [changedStyle, setChangedSTlye] = useState(false);
const styleHandler = () => {
changedStyle ? setChangedSTlye(false) : setChangedSTlye(true);
console.log("clicked");
console.log(changedStyle);
};
const List = Arr.map((l, index) => (
<ListElement key={index} onClick={styleHandler} className={changedStyle ? 'map-selected' : ''}>
{l.item}
</ListElement>
));
return List;
};
export default Map;
.map-selected{color:red;}
问题
这里的问题是changedStyle
是一个状态变量。因此,它不是数组元素所独有的,而是影响所有元素,因为它是 react
组件的状态。您需要 changedStyle
作为元素中的 属性。
一个解决方案
您的元素中需要有一个 changedStyle
标志。您可以使用 onClick
单击时更改数组中的元素。您将根据标志 l.changedStyle
动态分配一个 class 名称。您希望您的数组是一个状态变量,以便 React 组件在更改后重新呈现。
import React, { useState } from "react";
import './Map.css';
const Arr = [
{
id: "i1",
item: "item-1",
changedStyle: false
},
{
id: "i2",
item: "item-2",
changedStyle: false
},
{
id: "i3",
item: "item-3",
changedStyle: false
},
];
const ListElement = (props) => {
return <li className={props.className} onClick={props.onClick}>{props.children}</li>;
};
const Map = () => {
const [arr, setArr] = useState(Arr)
const styleHandler = (index) => {
const newArr = [...arr]
const element = newArr[index]
newArr.splice(index, 1, {...element, changedStyle: !element.changedStyle}
setArr(arr)
};
const List = arr.map((l, index) => (
<ListElement key={index} onClick={() => styleHandler(index)} className={l.changedStyle ? 'map-selected' : ''}>
{l.item}
</ListElement>
));
return List;
};
export default Map;
一个推荐
如果您的数组元素中有唯一的 id
或 key
,请不要在您的 jsx 中使用 key={index}
。而是使用 key={l.id}
而不是有一个标志来改变颜色。您需要维护一个列表,该列表将在选中时将所选项目的索引推送到列表中,并在再次单击时将其弹出。
const Map = () => {
const [ selectedItems , setSelectedItems] = useState([]);
const styleHandler = (itemIndex) => {
if(selectedItems.includes(itemIndex))
{
setSelectedItems(prevSelectedItems => prevSelectedItems.filter((item) => item !== itemIndex))
} else {
setSelectedItems(prevSelectedItems => [...prevSelectedItems, itemIndex])
}
};
const List = Arr.map((l, index) => (
<ListElement key={index} onClick={() => styleHandler(index)} className={selectedItems.includes(index) ? 'map-selected' : ''}>
{l.item}
</ListElement>
));
return List;
};
我们正在将 index
传递给 styleHandler 。第一次单击该项目时,我们将在 state 中推送该项目的索引。如果为第二个项目单击了相同的项目,那么我们会将其从状态中删除。
const styleHandler = (itemIndex) => {
if(selectedItems.includes(itemIndex))
{
setSelectedItems(prevSelectedItems => prevSelectedItems.filter((item) => item !== itemIndex))
} else {
setSelectedItems(prevSelectedItems => [...prevSelectedItems, itemIndex])
}
};
当 selectedItems 中存在项目索引时,我们应用样式
className={selectedItems.includes(index) ? 'map-selected' : ''}
这样就不需要维护添加标志或修改源数据了。
我已经映射了一组对象,如果单击其中一个元素,我想将该元素的颜色更改为红色(通过添加 CSS class),但它始终是彩色的所有的元素都是红色的。我以为 React 会自动获取上下文?我还需要使用 'this' 吗?
import React, { useState } from "react";
import './Map.css';
const Arr = [
{
id: "i1",
item: "item-1",
},
{
id: "i2",
item: "item-2",
},
{
id: "i3",
item: "item-3",
},
];
const ListElement = (props) => {
return <li className={props.className} onClick={props.onClick}>{props.children}</li>;
};
const Map = () => {
const [changedStyle, setChangedSTlye] = useState(false);
const styleHandler = () => {
changedStyle ? setChangedSTlye(false) : setChangedSTlye(true);
console.log("clicked");
console.log(changedStyle);
};
const List = Arr.map((l, index) => (
<ListElement key={index} onClick={styleHandler} className={changedStyle ? 'map-selected' : ''}>
{l.item}
</ListElement>
));
return List;
};
export default Map;
.map-selected{color:red;}
问题
这里的问题是changedStyle
是一个状态变量。因此,它不是数组元素所独有的,而是影响所有元素,因为它是 react
组件的状态。您需要 changedStyle
作为元素中的 属性。
一个解决方案
您的元素中需要有一个 changedStyle
标志。您可以使用 onClick
单击时更改数组中的元素。您将根据标志 l.changedStyle
动态分配一个 class 名称。您希望您的数组是一个状态变量,以便 React 组件在更改后重新呈现。
import React, { useState } from "react";
import './Map.css';
const Arr = [
{
id: "i1",
item: "item-1",
changedStyle: false
},
{
id: "i2",
item: "item-2",
changedStyle: false
},
{
id: "i3",
item: "item-3",
changedStyle: false
},
];
const ListElement = (props) => {
return <li className={props.className} onClick={props.onClick}>{props.children}</li>;
};
const Map = () => {
const [arr, setArr] = useState(Arr)
const styleHandler = (index) => {
const newArr = [...arr]
const element = newArr[index]
newArr.splice(index, 1, {...element, changedStyle: !element.changedStyle}
setArr(arr)
};
const List = arr.map((l, index) => (
<ListElement key={index} onClick={() => styleHandler(index)} className={l.changedStyle ? 'map-selected' : ''}>
{l.item}
</ListElement>
));
return List;
};
export default Map;
一个推荐
如果您的数组元素中有唯一的 id
或 key
,请不要在您的 jsx 中使用 key={index}
。而是使用 key={l.id}
而不是有一个标志来改变颜色。您需要维护一个列表,该列表将在选中时将所选项目的索引推送到列表中,并在再次单击时将其弹出。
const Map = () => {
const [ selectedItems , setSelectedItems] = useState([]);
const styleHandler = (itemIndex) => {
if(selectedItems.includes(itemIndex))
{
setSelectedItems(prevSelectedItems => prevSelectedItems.filter((item) => item !== itemIndex))
} else {
setSelectedItems(prevSelectedItems => [...prevSelectedItems, itemIndex])
}
};
const List = Arr.map((l, index) => (
<ListElement key={index} onClick={() => styleHandler(index)} className={selectedItems.includes(index) ? 'map-selected' : ''}>
{l.item}
</ListElement>
));
return List;
};
我们正在将 index
传递给 styleHandler 。第一次单击该项目时,我们将在 state 中推送该项目的索引。如果为第二个项目单击了相同的项目,那么我们会将其从状态中删除。
const styleHandler = (itemIndex) => {
if(selectedItems.includes(itemIndex))
{
setSelectedItems(prevSelectedItems => prevSelectedItems.filter((item) => item !== itemIndex))
} else {
setSelectedItems(prevSelectedItems => [...prevSelectedItems, itemIndex])
}
};
当 selectedItems 中存在项目索引时,我们应用样式
className={selectedItems.includes(index) ? 'map-selected' : ''}
这样就不需要维护添加标志或修改源数据了。