[英]How to change state on multiple elements in React during onClick event
當我單擊單個字體真棒圖標(6 個圖標中的 1 個)時,它的顏色會從灰色變為橙色,就像它應該的那樣。 我還想確保一次只有一個字體真棒圖標可以是橙色的。 因此,如果我單擊另一個圖標,以前是橙色的圖標現在是灰色的,而我剛剛單擊的圖標是橙色的。 我一直在努力實現這一目標,任何提示將不勝感激。
import React, { useState } from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
export default function FontAwesomeIcons(props) {
const [color, setColor] = useState(false);
const styles = {
display: "inline-flex",
justifyContent: "center",
margin: "10px",
color: color ? "orange" : "gray",
cursor: "pointer"
};
return (
<FontAwesomeIcon
onClick={() => setColor(!color)}
style={styles}
icon={props.name}
size='2x'
/>
);
}
它像我上面描述的那樣工作,但不像我想要的那樣。
有趣的。 問題是所有FontAwesomeIcons
共享相同的styles
對象。 因此,如果 color 為true
,則所有圖標都變為橙色。
你應該做的是將每個FontAwesomeIcon
移動到它自己的組件中,這樣它就可以管理自己的顏色state
和樣式對象。
這是一個工作沙箱: https : //codesandbox.io/s/billowing-frog-scci2
讓我們考慮這個例子:
import React from "react";
import FontAwesomeIcons from "./FontAwesomeIcons";
import { faCoffee, faUser, faTrash } from "@fortawesome/free-solid-svg-icons";
import ReactDOM from "react-dom";
import "./styles.css";
const icons = [faCoffee, faUser, faTrash];
const App = () => {
return (
<div>
<h4>Choose Food</h4>
<FontAwesomeIcons icons={icons} />
</div>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement)
在最上層的組件中,我們導入我們想要使用的字體很棒的圖標,並將它們放在一個名為 icons 的數組中。
我們將這些圖標傳遞給我們的子組件 FontAwesomeIcons,它接受該數組作為屬性。
import React, { useState } from "react";
import MyIcon from "./MyIcon";
const FontAwesomeIcons = props => {
const [selectedIndex, setSelectedIndex] = useState({});
const createIcons = () => {
const { icons } = props;
return icons.map((icon, iconIndex) => {
return (
<MyIcon
thisIcon={icon}
selectedIndex={selectedIndex}
iconIndex={iconIndex}
setSelectedIndex={setSelectedIndex}
size="2x"
/>
);
});
};
return createIcons();
};
export default FontAwesomeIcons;
在FontAwesomeIcons
,我們使用該icons
FontAwesomeIcons
,並對其iterate
以創建圖標集合。 我們不會直接使用 font-awesome 提供的FontAwesomeIcon
組件,而是將數組中的每個icon
傳遞給我們自己的MyIcon
組件的新實例。
此外,我們將跟蹤selectedIndex
狀態,以確定單擊了哪個圖標。 SelectedIndex
及其更新程序函數也作為道具傳遞給MyIcon
,這對於更新樣式對象至關重要。
import React, { useState, useEffect } from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
const MyIcon = props => {
const [color, setColor] = useState(false);
useEffect(() => {
if (props.selectedIndex === props.iconIndex) {
setColor(true);
} else {
setColor(false);
}
}, [props.selectedIndex]);
const styles = {
display: "inline-flex",
justifyContent: "center",
margin: "10px",
color: color ? "orange" : "gray",
cursor: "pointer"
};
return (
<div>
<FontAwesomeIcon
onClick={() => props.setSelectedIndex(props.iconIndex)}
style={styles}
icon={props.thisIcon}
size="2x"
/>
</div>
);
};
export default MyIcon;
最后,在我們的自定義MyIcon
組件中,我們將使用通過 props 傳遞的圖標呈現FontAwesomeIcon
。 請注意,每個 MyIcon 組件管理自己的color state
和樣式對象。
在FontAwesomeIcon
定義中,對於它的onClick()
我們執行作為 props (props.setSelectedIndex) 傳遞的狀態更新函數,並且我們給它屬於這個MyIcon
組件的圖標索引。 這會更新父級的選定狀態,並且該值將傳遞回MyIcon
以供我們評估。
因此,當您單擊 coffee-icon 時,您將selectedIndex
轉換為屬於初始數組的圖標的索引,該索引現在可以在MyIcon
中MyIcon
。 MyIcon 對象的所有實例都會重新渲染,並且在每個實例中,我們檢查selected
對象是否與其自己的圖標索引匹配。 如果是,我們將color-state
更改為true
(橙色),如果不是,我們將其更改為false
(灰色)。
總之,只要您的組件依賴於一個公共值,您就應該考慮創建一個中間狀態來幫助管理它們的功能。 簡而言之,這就是父子組件關系。
鑒於您提供的代碼片段,在我看來FontAwesomeIcons
是某個父組件的子組件。 在無法看到父組件的情況下,我將不得不假設您正在分別渲染每個組件。 因此,每個組件當前都彼此獨立運行。
要讓組件知道一個組件何時為橙色,這意味着您需要與每個子組件共享相同的數據。 想到了兩種方法。
1)您可以使用redux。 對於您正在嘗試做的事情來說有點笨重,但它會起作用。
2)您從父級傳遞一個函數,該函數控制按鈕的顏色狀態。 在父級中添加一些邏輯,您將獲得對按鈕布局的更多控制。
例如在您的父組件中:
...
render() {
return (
<div>
<FontAwesomeIcons onClick(() => {make magic})/>
<FontAwesomeIcons onClick(() => {make magic})/>
...
</div>
)
}
這當然不是創建多個圖標的最佳方式,但它可以說明問題。
您可以創建 fontawesome 圖標的一個通用(可重用)組件,並且可以在任何地方使用它 n 次,請查看此演示
您可以使用使用先前狀態的切換函數,然后您可以在單擊事件時調用該函數來完成這項工作。 不要忘記傳遞顏色代碼。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.