React 按钮和状态 - 如何避免状态过多?
React Buttons and State - how to avoid too many States?
我仍然是 React 的新手,还有很多东西要学。目前,我正在尝试制作一个页面,通过单击一个按钮来显示您想要的光剑和剑柄。我是通过使用状态来做到这一点的,从我目前拥有的状态数量来看,这似乎是错误的做法。
我是这样做的:我设置了一个状态并放置了一个 onClick 事件,该事件将所选 hilt/color 设置为 true,其余设置为 false,同时还呈现所述 hilt/color 的信息。它看起来像这样:
import { ReactComponent as QuiGon } from './qui-gon.svg';
import { ReactComponent as ObiWan } from './obi-wan.svg';
import { ReactComponent as ObiWanOld } from './obi-hilt-old.svg';
import { ReactComponent as DarthMaul } from './darth-maul-hilt.svg';
import { ReactComponent as AhsokaHilt } from './ahsoka-hilt.svg';
import { ReactComponent as AnakinHilt } from './anakin-hilt.svg';
import { ReactComponent as VaderHilt } from './darth-vader-hilt.svg';
import { ReactComponent as KyloHilt } from './kylo-ren-hilt.svg';
import './App.css';
function App() {
const [nonChosen, setNonChosen] = useState(true);
const [blue, setBlue] = useState(false);
const [red, setRed] = useState(false);
const [green, setGreen] = useState(false);
const [purple, setPurple] = useState(false);
const [yellow, setYellow] = useState(false);
const [white, setWhite] = useState(false);
const [saberOne, setSaberOne] = useState(true);
const [doubleSaber, setDoubleSaber] = useState(false);
const [quiGon, setQuiGon] = useState(false);
const [obiWanNew, setObiWanNew] = useState(false);
const [obiWanOld, setObiWanOld] = useState(false);
const [ahsoka, setAhsoka] = useState(false);
const [anakinHilt, setAnakinHilt] = useState(false);
const [vaderHilt, setVaderHilt] = useState(false);
const [kyloHilt, setKyloHilt] = useState(false);
return (
<div className="App">
{/* Colors */}
<button className="testsub" onClick={() => {setGreen(true); setWhite(false); setYellow(false); setPurple(false); setRed(false); setBlue(false); setNonChosen(false);}}>Green
</button>
<button className="testsub" onClick={() => {setBlue(true); setWhite(false); setYellow(false); setPurple(false); setRed(false); setGreen(false); setNonChosen(false);}}>Blue
</button>
<button className="testsub" onClick={() => {setRed(true); setWhite(false); setYellow(false); setPurple(false); setBlue(false); setGreen(false); setNonChosen(false);}}>Red
</button>
<button className="testsub" onClick={() => {setPurple(true); setWhite(false); setYellow(false); setGreen(false); setRed(false); setBlue(false); setNonChosen(false);}}>Purple
</button>
<button className="testsub" onClick={() => {setYellow(true); setWhite(false); setPurple(false); setGreen(false); setRed(false); setBlue(false); setNonChosen(false);}}>Yellow
</button>
<button className="testsub" onClick={() => {setWhite(true); setYellow(false); setPurple(false); setGreen(false); setRed(false); setBlue(false); setNonChosen(false);}}>White
</button>
<br />
{/* Hilts */}
<button className="testsub" onClick={() => {setDoubleSaber(true); setKyloHilt(false); setVaderHilt(false); setAnakinHilt(false); setAhsoka(false); setSaberOne(false); setQuiGon(false); setObiWanNew(false); setObiWanOld(false);}}>Darth Maul
</button>
<button className="testsub" onClick={() => {setQuiGon(true); setKyloHilt(false); setVaderHilt(false); setAnakinHilt(false); setAhsoka(false); setDoubleSaber(false); setSaberOne(false); setObiWanNew(false); setObiWanOld(false);}}>Qui Gon
</button>
<button className="testsub" onClick={() => {setObiWanNew(true); setKyloHilt(false); setVaderHilt(false); setAnakinHilt(false); setAhsoka(false); setDoubleSaber(false); setSaberOne(false); setQuiGon(false); setObiWanOld(false);}}>Obi Wan
</button>
<button className="testsub" onClick={() => {setObiWanOld(true); setKyloHilt(false); setVaderHilt(false); setAnakinHilt(false); setAhsoka(false); setDoubleSaber(false); setSaberOne(false); setQuiGon(false); setObiWanNew(false);}}>Obi Wan Old
</button>
<button className="testsub" onClick={() => {setAhsoka(true); setKyloHilt(false); setVaderHilt(false); setAnakinHilt(false); setObiWanOld(false); setDoubleSaber(false); setSaberOne(false); setQuiGon(false); setObiWanNew(false);}}>Ahsoka Tano
</button>
<button className="testsub" onClick={() => {setAnakinHilt(true); setKyloHilt(false); setVaderHilt(false); setAhsoka(false); setObiWanOld(false); setDoubleSaber(false); setSaberOne(false); setQuiGon(false); setObiWanNew(false);}}>Anakin
</button>
<button className="testsub" onClick={() => {setVaderHilt(true); setKyloHilt(false); setAnakinHilt(false); setAhsoka(false); setObiWanOld(false); setDoubleSaber(false); setSaberOne(false); setQuiGon(false); setObiWanNew(false);}}>Vader
</button>
<button className="testsub" onClick={() => { setKyloHilt(true);setVaderHilt(false); setAnakinHilt(false); setAhsoka(false); setObiWanOld(false); setDoubleSaber(false); setSaberOne(false); setQuiGon(false); setObiWanNew(false);}}>Kylo
</button>
<div class="lightsaber">
<input type="checkbox" id="on-off" />
{nonChosen && (
<>
<div className="blade colol"></div>
{/* <div className="blade2 colol"></div> */}
</>
)}
{blue && (
<div className="blade colol2"></div>
)}
{red && (
<div className="blade red-clr"></div>
)}
{green && (
<div className="blade colol"></div>
)}
{purple && (
<div className="blade purple-clr"></div>
)}
{yellow && (
<div className="blade yellow-clr"></div>
)}
{white && (
<div className="blade white-clr"></div>
)}
{saberOne && (
<label className="hilt" for="on-off">
<QuiGon />
</label>
)}
{doubleSaber && (
<>
<div className="blade2 colol"></div>
<label className="hilt" for="on-off">
<DarthMaul />
</label>
</>
)}
{quiGon && (
<label className="hilt" for="on-off">
<QuiGon />
</label>
)}
{obiWanNew && (
<label className="hilt" for="on-off">
<ObiWan />
</label>
)}
{obiWanOld && (
<label className="hilt" for="on-off">
<ObiWanOld />
</label>
)}
{ahsoka && (
<label className="hilt" for="on-off">
<AhsokaHilt />
</label>
)}
{anakinHilt && (
<label className="hilt" for="on-off">
<AnakinHilt />
</label>
)}
{vaderHilt && (
<label className="hilt" for="on-off">
<VaderHilt />
</label>
)}
{kyloHilt && (
// <label className="hilt" for="on-off">
// <KyloHilt className="hilt2"/>
// </label>
<>
<div className="blade3 colol"></div>
<div className="blade4 colol"></div>
<label className="hilt" for="on-off">
<KyloHilt className="hilt2"/>
</label>
</>
)}
</div>
<div className="infobox">
{nonChosen && (
<div>Yoyoyo</div>
)}
{blue && (
<div>aasdsd</div>
)}
{green && (
<div>fgfgfg</div>
)}
</div>
</div>
);
}
export default App;
还没有完成所以有点乱,不过问题还是很不错的。我有很多状态,所有 setX(false) 按钮变得很长。
有什么更好的方法吗?我已经思考了很长时间关于如何使用 CSS、if/else 等,但我似乎无法理解如何让按钮显示一件事并离开休息隐藏,而不必像我已经那样过度指定它。我还是个新手,所以真的很感激任何帮助(再次对意大利面条代码感到抱歉)!
您可以初始化对象中的值并将它们用作初始状态
const initialValues = {
nonChosen: true,
blue: false,
red: false,
green: false,
purple: false,
yellow: false,
white: false,
// All other states in this or create a seperate object with seperate useState according to your wish
};
并将状态初始化为
const [colors, setColors] = useState(initialValues);
将onClick期间的值设置为
<button className="testsub" onClick={() => {setColors({...colors,green:true,white:false,yellow:false,purple:false,red:false,blue:false,nonchosen:false})>Green</button>
渲染期间:
{colors.nonChosen && (
<>
<div className="blade colol"></div>
{/* <div className="blade2 colol"></div> */}
</>
)}
您可以使用 useReducer 钩子。
此外,您可以内联事件(用于颜色)或回调事件(用于刀柄)。
我用了两个案例。
const initialColorState = {
nonChosen: false,
blue: false,
red: false,
green: false,
purple: false,
yellow: false,
white: false,
};
const initialHiltState = {
saberOne: false,
doubleSaber: false,
quiGon: false,
obiWanNew: false,
obiWanOld: false,
ahsoka: false,
anakinHilt: false,
vaderHilt: false,
kyloHilt: false
}
function colorReducer(state, action) {
switch (action.type) {
case "Blue": {
return {
...state,
...initialColorState,
blue: true,
}
}
case "Red": {
return {
...state,
...initialColorState,
red: true,
}
}
case "Green": {
return {
...state,
...initialColorState,
green: true,
}
}
case "Purple": {
return {
...state,
...initialColorState,
purple: true,
}
}
case "Yellow": {
return {
...state,
...initialColorState,
yellow: true,
}
}
case "White": {
return {
...state,
...initialColorState,
white: true,
}
}
}
}
function hiltReducer(state, action) {
switch (action.type) {
case "DoubleSaber": {
return {
...state,
...initialHiltState,
doubleSaber: true,
}
}
case "QuiGon": {
return {
...state,
...initialHiltState,
quiGon: true,
}
}
case "ObiWanNew": {
return {
...state,
...initialHiltState,
obiWanNew: true,
}
}
case "ObiWanOld": {
return {
...state,
...initialHiltState,
obiWanOld: true,
}
}
case "Ahsoka": {
return {
...state,
...initialHiltState,
ahsoka: true,
}
}
case "Anakin": {
return {
...state,
...initialHiltState,
anakinHilt: true,
}
}
case "Vader": {
return {
...state,
...initialHiltState,
vaderHilt: true,
}
}
case "Kylo": {
return {
...state,
...initialHiltState,
kyloHilt: true,
}
}
}
}
function App() {
const [colorState, colorDispatch] = useReducer(colorReducer, initialColorState)
const [hiltState, hiltDispatch] = useReducer(hiltReducer, initialHiltState);
const onHiltClick = useCallback((event) => {
hiltDispatch({type: event.value});
}, [hiltDispatch]);
return (
<div className="App">
{/* Colors */}
<button
className="testsub"
onClick={() => {
colorDispatch({ type: "Green" })
}}
>
Green
</button>
<button
className="testsub"
onClick={() => {
colorDispatch({ type: "Blue" })
}}
>
Blue
</button>
<button
className="testsub"
onClick={() => {
colorDispatch({ type: "Red" })
}}
>
Red
</button>
<button
className="testsub"
onClick={() => {
colorDispatch({ type: "Purple" })
}}
>
Purple
</button>
<button
className="testsub"
onClick={() => {
colorDispatch({ type: "Yellow" })
}}
>
Yellow
</button>
<button
className="testsub"
onClick={() => {
colorDispatch({ type: "White" })
}}
>
White
</button>
<br />
{/* Hilts */}
<button className="testsub" onClick={onHiltClick} value="DoubleSaber">
Darth Maul
</button>
<button className="testsub" onClick={onHiltClick} value="QuiGon">
Qui Gon
</button>
<button className="testsub" onClick={onHiltClick} value="ObiWanNew">
Obi Wan
</button>
<button className="testsub" onClick={onHiltClick} value="ObiWanOld">
Obi Wan Old
</button>
<button className="testsub" onClick={onHiltClick} value="Ahsoka">
Ahsoka Tano
</button>
<button className="testsub" onClick={onHiltClick} value="Anakin">
Anakin
</button>
<button className="testsub" onClick={onHiltClick} value="Vader">
Vader
</button>
<button className="testsub" onClick={onHiltClick} value="Kylo">
Kylo
</button>
.....
)
}
export default App;
我仍然是 React 的新手,还有很多东西要学。目前,我正在尝试制作一个页面,通过单击一个按钮来显示您想要的光剑和剑柄。我是通过使用状态来做到这一点的,从我目前拥有的状态数量来看,这似乎是错误的做法。
我是这样做的:我设置了一个状态并放置了一个 onClick 事件,该事件将所选 hilt/color 设置为 true,其余设置为 false,同时还呈现所述 hilt/color 的信息。它看起来像这样:
import { ReactComponent as QuiGon } from './qui-gon.svg';
import { ReactComponent as ObiWan } from './obi-wan.svg';
import { ReactComponent as ObiWanOld } from './obi-hilt-old.svg';
import { ReactComponent as DarthMaul } from './darth-maul-hilt.svg';
import { ReactComponent as AhsokaHilt } from './ahsoka-hilt.svg';
import { ReactComponent as AnakinHilt } from './anakin-hilt.svg';
import { ReactComponent as VaderHilt } from './darth-vader-hilt.svg';
import { ReactComponent as KyloHilt } from './kylo-ren-hilt.svg';
import './App.css';
function App() {
const [nonChosen, setNonChosen] = useState(true);
const [blue, setBlue] = useState(false);
const [red, setRed] = useState(false);
const [green, setGreen] = useState(false);
const [purple, setPurple] = useState(false);
const [yellow, setYellow] = useState(false);
const [white, setWhite] = useState(false);
const [saberOne, setSaberOne] = useState(true);
const [doubleSaber, setDoubleSaber] = useState(false);
const [quiGon, setQuiGon] = useState(false);
const [obiWanNew, setObiWanNew] = useState(false);
const [obiWanOld, setObiWanOld] = useState(false);
const [ahsoka, setAhsoka] = useState(false);
const [anakinHilt, setAnakinHilt] = useState(false);
const [vaderHilt, setVaderHilt] = useState(false);
const [kyloHilt, setKyloHilt] = useState(false);
return (
<div className="App">
{/* Colors */}
<button className="testsub" onClick={() => {setGreen(true); setWhite(false); setYellow(false); setPurple(false); setRed(false); setBlue(false); setNonChosen(false);}}>Green
</button>
<button className="testsub" onClick={() => {setBlue(true); setWhite(false); setYellow(false); setPurple(false); setRed(false); setGreen(false); setNonChosen(false);}}>Blue
</button>
<button className="testsub" onClick={() => {setRed(true); setWhite(false); setYellow(false); setPurple(false); setBlue(false); setGreen(false); setNonChosen(false);}}>Red
</button>
<button className="testsub" onClick={() => {setPurple(true); setWhite(false); setYellow(false); setGreen(false); setRed(false); setBlue(false); setNonChosen(false);}}>Purple
</button>
<button className="testsub" onClick={() => {setYellow(true); setWhite(false); setPurple(false); setGreen(false); setRed(false); setBlue(false); setNonChosen(false);}}>Yellow
</button>
<button className="testsub" onClick={() => {setWhite(true); setYellow(false); setPurple(false); setGreen(false); setRed(false); setBlue(false); setNonChosen(false);}}>White
</button>
<br />
{/* Hilts */}
<button className="testsub" onClick={() => {setDoubleSaber(true); setKyloHilt(false); setVaderHilt(false); setAnakinHilt(false); setAhsoka(false); setSaberOne(false); setQuiGon(false); setObiWanNew(false); setObiWanOld(false);}}>Darth Maul
</button>
<button className="testsub" onClick={() => {setQuiGon(true); setKyloHilt(false); setVaderHilt(false); setAnakinHilt(false); setAhsoka(false); setDoubleSaber(false); setSaberOne(false); setObiWanNew(false); setObiWanOld(false);}}>Qui Gon
</button>
<button className="testsub" onClick={() => {setObiWanNew(true); setKyloHilt(false); setVaderHilt(false); setAnakinHilt(false); setAhsoka(false); setDoubleSaber(false); setSaberOne(false); setQuiGon(false); setObiWanOld(false);}}>Obi Wan
</button>
<button className="testsub" onClick={() => {setObiWanOld(true); setKyloHilt(false); setVaderHilt(false); setAnakinHilt(false); setAhsoka(false); setDoubleSaber(false); setSaberOne(false); setQuiGon(false); setObiWanNew(false);}}>Obi Wan Old
</button>
<button className="testsub" onClick={() => {setAhsoka(true); setKyloHilt(false); setVaderHilt(false); setAnakinHilt(false); setObiWanOld(false); setDoubleSaber(false); setSaberOne(false); setQuiGon(false); setObiWanNew(false);}}>Ahsoka Tano
</button>
<button className="testsub" onClick={() => {setAnakinHilt(true); setKyloHilt(false); setVaderHilt(false); setAhsoka(false); setObiWanOld(false); setDoubleSaber(false); setSaberOne(false); setQuiGon(false); setObiWanNew(false);}}>Anakin
</button>
<button className="testsub" onClick={() => {setVaderHilt(true); setKyloHilt(false); setAnakinHilt(false); setAhsoka(false); setObiWanOld(false); setDoubleSaber(false); setSaberOne(false); setQuiGon(false); setObiWanNew(false);}}>Vader
</button>
<button className="testsub" onClick={() => { setKyloHilt(true);setVaderHilt(false); setAnakinHilt(false); setAhsoka(false); setObiWanOld(false); setDoubleSaber(false); setSaberOne(false); setQuiGon(false); setObiWanNew(false);}}>Kylo
</button>
<div class="lightsaber">
<input type="checkbox" id="on-off" />
{nonChosen && (
<>
<div className="blade colol"></div>
{/* <div className="blade2 colol"></div> */}
</>
)}
{blue && (
<div className="blade colol2"></div>
)}
{red && (
<div className="blade red-clr"></div>
)}
{green && (
<div className="blade colol"></div>
)}
{purple && (
<div className="blade purple-clr"></div>
)}
{yellow && (
<div className="blade yellow-clr"></div>
)}
{white && (
<div className="blade white-clr"></div>
)}
{saberOne && (
<label className="hilt" for="on-off">
<QuiGon />
</label>
)}
{doubleSaber && (
<>
<div className="blade2 colol"></div>
<label className="hilt" for="on-off">
<DarthMaul />
</label>
</>
)}
{quiGon && (
<label className="hilt" for="on-off">
<QuiGon />
</label>
)}
{obiWanNew && (
<label className="hilt" for="on-off">
<ObiWan />
</label>
)}
{obiWanOld && (
<label className="hilt" for="on-off">
<ObiWanOld />
</label>
)}
{ahsoka && (
<label className="hilt" for="on-off">
<AhsokaHilt />
</label>
)}
{anakinHilt && (
<label className="hilt" for="on-off">
<AnakinHilt />
</label>
)}
{vaderHilt && (
<label className="hilt" for="on-off">
<VaderHilt />
</label>
)}
{kyloHilt && (
// <label className="hilt" for="on-off">
// <KyloHilt className="hilt2"/>
// </label>
<>
<div className="blade3 colol"></div>
<div className="blade4 colol"></div>
<label className="hilt" for="on-off">
<KyloHilt className="hilt2"/>
</label>
</>
)}
</div>
<div className="infobox">
{nonChosen && (
<div>Yoyoyo</div>
)}
{blue && (
<div>aasdsd</div>
)}
{green && (
<div>fgfgfg</div>
)}
</div>
</div>
);
}
export default App;
还没有完成所以有点乱,不过问题还是很不错的。我有很多状态,所有 setX(false) 按钮变得很长。
有什么更好的方法吗?我已经思考了很长时间关于如何使用 CSS、if/else 等,但我似乎无法理解如何让按钮显示一件事并离开休息隐藏,而不必像我已经那样过度指定它。我还是个新手,所以真的很感激任何帮助(再次对意大利面条代码感到抱歉)!
您可以初始化对象中的值并将它们用作初始状态
const initialValues = {
nonChosen: true,
blue: false,
red: false,
green: false,
purple: false,
yellow: false,
white: false,
// All other states in this or create a seperate object with seperate useState according to your wish
};
并将状态初始化为
const [colors, setColors] = useState(initialValues);
将onClick期间的值设置为
<button className="testsub" onClick={() => {setColors({...colors,green:true,white:false,yellow:false,purple:false,red:false,blue:false,nonchosen:false})>Green</button>
渲染期间:
{colors.nonChosen && (
<>
<div className="blade colol"></div>
{/* <div className="blade2 colol"></div> */}
</>
)}
您可以使用 useReducer 钩子。 此外,您可以内联事件(用于颜色)或回调事件(用于刀柄)。 我用了两个案例。
const initialColorState = {
nonChosen: false,
blue: false,
red: false,
green: false,
purple: false,
yellow: false,
white: false,
};
const initialHiltState = {
saberOne: false,
doubleSaber: false,
quiGon: false,
obiWanNew: false,
obiWanOld: false,
ahsoka: false,
anakinHilt: false,
vaderHilt: false,
kyloHilt: false
}
function colorReducer(state, action) {
switch (action.type) {
case "Blue": {
return {
...state,
...initialColorState,
blue: true,
}
}
case "Red": {
return {
...state,
...initialColorState,
red: true,
}
}
case "Green": {
return {
...state,
...initialColorState,
green: true,
}
}
case "Purple": {
return {
...state,
...initialColorState,
purple: true,
}
}
case "Yellow": {
return {
...state,
...initialColorState,
yellow: true,
}
}
case "White": {
return {
...state,
...initialColorState,
white: true,
}
}
}
}
function hiltReducer(state, action) {
switch (action.type) {
case "DoubleSaber": {
return {
...state,
...initialHiltState,
doubleSaber: true,
}
}
case "QuiGon": {
return {
...state,
...initialHiltState,
quiGon: true,
}
}
case "ObiWanNew": {
return {
...state,
...initialHiltState,
obiWanNew: true,
}
}
case "ObiWanOld": {
return {
...state,
...initialHiltState,
obiWanOld: true,
}
}
case "Ahsoka": {
return {
...state,
...initialHiltState,
ahsoka: true,
}
}
case "Anakin": {
return {
...state,
...initialHiltState,
anakinHilt: true,
}
}
case "Vader": {
return {
...state,
...initialHiltState,
vaderHilt: true,
}
}
case "Kylo": {
return {
...state,
...initialHiltState,
kyloHilt: true,
}
}
}
}
function App() {
const [colorState, colorDispatch] = useReducer(colorReducer, initialColorState)
const [hiltState, hiltDispatch] = useReducer(hiltReducer, initialHiltState);
const onHiltClick = useCallback((event) => {
hiltDispatch({type: event.value});
}, [hiltDispatch]);
return (
<div className="App">
{/* Colors */}
<button
className="testsub"
onClick={() => {
colorDispatch({ type: "Green" })
}}
>
Green
</button>
<button
className="testsub"
onClick={() => {
colorDispatch({ type: "Blue" })
}}
>
Blue
</button>
<button
className="testsub"
onClick={() => {
colorDispatch({ type: "Red" })
}}
>
Red
</button>
<button
className="testsub"
onClick={() => {
colorDispatch({ type: "Purple" })
}}
>
Purple
</button>
<button
className="testsub"
onClick={() => {
colorDispatch({ type: "Yellow" })
}}
>
Yellow
</button>
<button
className="testsub"
onClick={() => {
colorDispatch({ type: "White" })
}}
>
White
</button>
<br />
{/* Hilts */}
<button className="testsub" onClick={onHiltClick} value="DoubleSaber">
Darth Maul
</button>
<button className="testsub" onClick={onHiltClick} value="QuiGon">
Qui Gon
</button>
<button className="testsub" onClick={onHiltClick} value="ObiWanNew">
Obi Wan
</button>
<button className="testsub" onClick={onHiltClick} value="ObiWanOld">
Obi Wan Old
</button>
<button className="testsub" onClick={onHiltClick} value="Ahsoka">
Ahsoka Tano
</button>
<button className="testsub" onClick={onHiltClick} value="Anakin">
Anakin
</button>
<button className="testsub" onClick={onHiltClick} value="Vader">
Vader
</button>
<button className="testsub" onClick={onHiltClick} value="Kylo">
Kylo
</button>
.....
)
}
export default App;