Styled Components事件处理器使用问题:点击无法正确更新useState
问题分析与解决办法
为什么会出现这个问题?
你写的onClick={(key)=>setIndex(key)}里,那个key参数其实不是map循环的索引——React的点击事件回调第一个参数永远是事件对象(SyntheticBaseEvent),你用key当参数名,直接把map的索引变量给覆盖了,所以调用setIndex时传的是事件对象,不是你要的索引值。
怎么修?
两种简单方法:
方法1:换个参数名
把事件参数改成别的名字(比如e),这样就能正确引用map的key了:
<Index onClick={(e) => setIndex(key)}>{key + 1}</Index>
方法2:直接用闭包的索引
如果不需要事件对象,直接写个无参箭头函数就行:
<Index onClick={() => setIndex(key)}>{key + 1}</Index>
额外优化建议
React循环渲染的时候,每个项最好加个唯一key属性,不然控制台会弹警告。你可以给外层的Fragment加上:
{navitems.map((item, key) => { return ( <React.Fragment key={key}> <Index onClick={() => setIndex(key)}>{key + 1}</Index> <Heading>{item.step}</Heading> <Content>{item.value}</Content> </React.Fragment> ); })}
(注意用带key的Fragment得写完整的React.Fragment,不能用<>短语法)
修复后的完整代码
import React, { useState } from "react"; import styled from "styled-components"; import pic from "./assets/images/bg-sidebar-desktop.svg"; const App=()=> { const [index, setIndex] = useState(0); const navitems = [ { step: "Step 1", value: "Your info" }, { step: "Step 2", value: "Select plan" }, { step: "Step 3", value: "Add-ons" }, { step: "Step 4", value: "Summary" }, ]; return ( <Container> <Navbar imgUrl={pic}> {navitems.map((item, key) => ( <React.Fragment key={key}> <Index onClick={() => setIndex(key)}>{key + 1}</Index> <Heading>{item.step}</Heading> <Content>{item.value}</Content> </React.Fragment> ))} </Navbar> </Container> ); } // 样式组件保持不变 const Container = styled.div` height: 70.5vh; width: 55vw; margin: auto; margin-top: calc(100vh / 7); border-radius: 1em; background-color: white; overflow: hidden; font-size: .9em; `; const Navbar = styled.div` border: 1px solid black; background-image: url(${(props) => props.imgUrl}); background-repeat: no-repeat; background-position: 100% 100%; height: 66.7vh; width: 15.5vw; border-radius: 1em; margin-top: calc((3.6vh) / 2); margin-left: 0.8em; color: #ffffff; text-transform: uppercase; `; const Heading = styled.div` color: hsl(231, 11%, 63%); text-indent: 5.5em; letter-spacing: .005em; font-size: .9em; `; const Content = styled.div` text-indent: 5em; letter-spacing: .1em; font-weight: bolder; `; const Index = styled.span` border: 1px solid white; display: inline-block; border-radius: 50%; height: 2em; width: 2em; text-align: center; padding-top: 0.3em; box-sizing: border-box; position: relative; top: 7%; left: 10%; `; export default App;
内容的提问来源于stack exchange,提问作者Devansh
相关产品推荐
相关产品推荐

