ReactJs:为什么渲染组件时 ref.current returns null?
ReactJs: Why ref.current returns null when the component is rendered?
我在购物车内有一个按钮,我想在购物车打开时给它一个动画。为了定位它,我使用了 useRef 并尝试登录控制台结果:
const checkoutBtnRef = useRef("null");
useEffect(() => {
console.log(checkoutBtnRef.current);
}, [cartOpen]);
问题是当我打开购物车时 current 为空,而 returns 只有当我关闭购物车时才是实际的按钮,我预计它是相反的。
有什么想法吗?
完整组件代码
export default function TopNav() {
const classes = useStyles();
const [cartOpen, setCartOpen] = useState(false);
const checkoutBtnRef = useRef("null");
useEffect(() => {
console.log(checkoutBtnRef.current);
}, [cartOpen]);
return (
<>
<Container maxWidth="xl">
<div className={classes.root}>
<CardMedia
image="https://www.example.com"
className={classes.media}
/>
<SearchBar placeholder="Search" className={classes.searchBar} />
<div className={classes.iconsContainer}>
<PersonIcon className={classes.icon} />
<FavoriteBorderIcon className={classes.icon} />
<Badge
invisible={false}
variant="dot"
color="error"
onClick={() => setCartOpen(true)}
>
<ShoppingBasketIcon className={classes.icon} />
</Badge>
</div>
</div>
</Container>
<Drawer
classes={{
paper: classes.cart,
}}
anchor="right"
open={cartOpen}
transitionDuration={{ enter: 500, exit: 200 }}
onClose={() => setCartOpen(false)}
>
<div className={classes.topCartContent}>
<Typography variant="h5">Cart</Typography>
<CloseIcon
className={classes.closeIcon}
onClick={() => setCartOpen(false)}
/>
</div>
<Divider />
<List>
<CartItem />
</List>
<Button
classes={{
root: classes.checkoutBtn,
}}
variant="outlined"
onClick={() => setCartOpen(false)}
ref={checkoutBtnRef}
>
checkout
</Button>
</Drawer>
</>
);
}
编辑:
你的抽屉有延迟,你的按钮还没有呈现,所以你看不到 cartOpen 更改事件上的按钮......
所以使用它来存储和调用您的函数而不是 useEffect。
const checkoutBtnRef = (ref) => {
console.log(ref);
if (ref){
// do ur staff here
}
};
如果你需要useEffect
你可以这样做:
const [btnRef, setBtnRef] = useState(null);
const checkoutBtnRef = (ref) => {
if (ref) setBtnRef(ref);
};
useEffect(() => {
console.log(btnRef);
}, [btnRef]);
旧答案:
const App = ()=>{
const [cart,setCart]= React.useState(false);
const [btnRef, setBtnRef] = React.useState(null);
const checkoutBtnRef = (ref) => {
if (ref) setBtnRef(ref);
else setBtnRef(null)
};
React.useEffect(() => {
console.log(btnRef);
}, [btnRef]);
const cartHandler = () => {
setTimeout(()=>{
setCart((prev) => !prev)
},1000);
};
return (
<React.Fragment>
<button onClick={cartHandler}>
Cart
</button>
{cart && <button ref={checkoutBtnRef}>Check Out</button>}
</React.Fragment>
)
}
ReactDOM.render(
<App />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>
我在购物车内有一个按钮,我想在购物车打开时给它一个动画。为了定位它,我使用了 useRef 并尝试登录控制台结果:
const checkoutBtnRef = useRef("null");
useEffect(() => {
console.log(checkoutBtnRef.current);
}, [cartOpen]);
问题是当我打开购物车时 current 为空,而 returns 只有当我关闭购物车时才是实际的按钮,我预计它是相反的。 有什么想法吗?
完整组件代码
export default function TopNav() {
const classes = useStyles();
const [cartOpen, setCartOpen] = useState(false);
const checkoutBtnRef = useRef("null");
useEffect(() => {
console.log(checkoutBtnRef.current);
}, [cartOpen]);
return (
<>
<Container maxWidth="xl">
<div className={classes.root}>
<CardMedia
image="https://www.example.com"
className={classes.media}
/>
<SearchBar placeholder="Search" className={classes.searchBar} />
<div className={classes.iconsContainer}>
<PersonIcon className={classes.icon} />
<FavoriteBorderIcon className={classes.icon} />
<Badge
invisible={false}
variant="dot"
color="error"
onClick={() => setCartOpen(true)}
>
<ShoppingBasketIcon className={classes.icon} />
</Badge>
</div>
</div>
</Container>
<Drawer
classes={{
paper: classes.cart,
}}
anchor="right"
open={cartOpen}
transitionDuration={{ enter: 500, exit: 200 }}
onClose={() => setCartOpen(false)}
>
<div className={classes.topCartContent}>
<Typography variant="h5">Cart</Typography>
<CloseIcon
className={classes.closeIcon}
onClick={() => setCartOpen(false)}
/>
</div>
<Divider />
<List>
<CartItem />
</List>
<Button
classes={{
root: classes.checkoutBtn,
}}
variant="outlined"
onClick={() => setCartOpen(false)}
ref={checkoutBtnRef}
>
checkout
</Button>
</Drawer>
</>
);
}
编辑: 你的抽屉有延迟,你的按钮还没有呈现,所以你看不到 cartOpen 更改事件上的按钮......
所以使用它来存储和调用您的函数而不是 useEffect。
const checkoutBtnRef = (ref) => {
console.log(ref);
if (ref){
// do ur staff here
}
};
如果你需要useEffect
你可以这样做:
const [btnRef, setBtnRef] = useState(null);
const checkoutBtnRef = (ref) => {
if (ref) setBtnRef(ref);
};
useEffect(() => {
console.log(btnRef);
}, [btnRef]);
旧答案:
const App = ()=>{
const [cart,setCart]= React.useState(false);
const [btnRef, setBtnRef] = React.useState(null);
const checkoutBtnRef = (ref) => {
if (ref) setBtnRef(ref);
else setBtnRef(null)
};
React.useEffect(() => {
console.log(btnRef);
}, [btnRef]);
const cartHandler = () => {
setTimeout(()=>{
setCart((prev) => !prev)
},1000);
};
return (
<React.Fragment>
<button onClick={cartHandler}>
Cart
</button>
{cart && <button ref={checkoutBtnRef}>Check Out</button>}
</React.Fragment>
)
}
ReactDOM.render(
<App />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>