[英]React setting initial state based on one of child components parameters
我正在制作一个带有菜单栏和滑动选定菜单项指示器的应用程序。 它有点工作,但我有几个问题:
widthOffset
, leftOffset
和color
)是硬编码的,但我需要它始终遵循活动的NavLink
,所以当我打开我的应用程序时 - 指示器立即在所选NavLink
的正确位置(如果你 select 除了Home
NavLink
并重新加载应用程序,您将在最后一页,但指示器重置为硬编码状态)。e.target
获取activeStyle
值的方法,因此 colors 在每个NavLink
中也用这个双menuItems.*NavLink name*.color
进行了奇怪的硬编码。实现这一点的最佳方法是什么?
完整的代码框: https://codesandbox.io/s/ecstatic-moon-mqbnk
代码:
import React, { useState } from "react";
import { NavLink } from "react-router-dom";
const Navigation = () => {
const menuItems = {
Home: {
color: 'orange',
},
About: {
color: 'green',
},
Contacts: {
color: 'rebeccapurple',
},
}
const [offsetWidth, setWidth] = useState(84);
const [offsetLeft, setLeft] = useState(26);
const [color, setColor] = useState("orange");
function switchMenu(e, color) {
setWidth(e.target.offsetWidth);
setLeft(e.target.offsetLeft);
setColor(color);
}
return (
<nav className="nav">
<NavLink
refs="Home"
exact
className="nav-item"
activeClassName="nav-item is active"
activeStyle={{ color: menuItems.Home.color }}
to="/"
onClick={(e) => switchMenu(e, menuItems.Home.color)}
>
Home
</NavLink>
<NavLink
refs="About"
exact
className="nav-item"
activeClassName="nav-item is active"
activeStyle={{ color: menuItems.About.color }}
to="/about"
onClick={(e) => switchMenu(e, menuItems.About.color)}
>
About
</NavLink>
<NavLink
refs="Contacts"
exact
className="nav-item"
activeClassName="nav-item is active"
activeStyle={{ color: menuItems.Contacts.color }}
to="/contact"
onClick={(e) => switchMenu(e, menuItems.Contacts.color)}
>
Contacts
</NavLink>
<span
style={{
position: "absolute",
left: `${offsetLeft}px`,
width: `${offsetWidth}px`,
backgroundColor: `${color}`,
bottom: "0px",
height: "5px",
transition: ".4s",
zIndex: "1",
borderRadius: "8px 8px 0 0",
}}
></span>
</nav>
);
};
export default Navigation;
升级版:
我设法解决了一些问题,使用NavLink
的isActive
,现在指示器总是在适当的位置,但仍然有点麻烦:
onClick
,这会破坏 state 和 React 的重新渲染能力。 当我更改选定的链接时,我没有找到一种方法来切换useEffect
以重新呈现指示器。 此外,当我尝试不直接更改 state onClick
,但运行setCurrentPage()
它工作 1/2 次,导致onClick
发生更胖,而不是类。Ctrl + F5
并且 fonts 等会跳转 - 指示器会呈现一点点不在它的位置。 如果我能在一切都解决后渲染它会很好。更新的代码框: https://codesandbox.io/s/strange-shadow-5jo68
更新了 Navigattion.js 代码:
import React, { useState, useRef, useEffect } from "react";
import { NavLink } from "react-router-dom";
const Navigation = () => {
const [offsetWidth, setWidth] = useState(null);
const [offsetLeft, setLeft] = useState(null);
const [color, setColor] = useState(null);
const Home = useRef(null);
const About = useRef(null);
const Contacts = useRef(null);
const menuItems = {
Home: {
ref: Home,
color: "orange",
},
About: {
ref: About,
color: "green",
},
Contacts: {
ref: Contacts,
color: "rebeccapurple",
},
};
function changeIndicator(e, color) {
setWidth(e.offsetWidth);
setLeft(e.offsetLeft);
setColor(color);
}
function setCurrentPage() {
Object.keys(menuItems).forEach((key) => {
if (
menuItems[key].ref.current.className === "nav-item nav-item is active"
) {
changeIndicator(menuItems[key].ref.current, menuItems[key].color);
}
});
}
useEffect(setCurrentPage);
return (
<nav className="nav">
<NavLink
ref={Home}
isActive={(match) => {
if (!match) {
return false;
}
return true;
}}
exact
className="nav-item"
activeClassName="nav-item is active"
activeStyle={{ color: menuItems.Home.color }}
to="/"
onClick={(e) => changeIndicator(e.target, menuItems.Home.color)}
>
Home
</NavLink>
...
正如我在评论中所说,您可以使用参考来检查活动链接是什么,然后设置 state
is-active
className="nav-item"
activeClassName="is-active"
const homeLink = useRef(null);
const aboutLink = useRef(null);
const contactLink = useRef(null);
useEffect(() => {
if (homeLink.current.className.includes("is-active")) {
setWidth(homeLink.current.offsetWidth);
setLeft(homeLink.current.offsetLeft);
setColor(menuItems.Home.color);
} else if (aboutLink.current.className.includes("is-active")) {
setWidth(aboutLink.current.offsetWidth);
setLeft(aboutLink.current.offsetLeft);
setColor(menuItems.About.color);
} else if (contactLink.current.className.includes("is-active")) {
setWidth(contactLink.current.offsetWidth);
setLeft(contactLink.current.offsetLeft);
setColor(menuItems.Contacts.color);
}
}, []);
....
<NavLink
ref={homeLink}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.