繁体   English   中英

根据子组件参数之一反应设置初始 state

[英]React setting initial state based on one of child components parameters

我正在制作一个带有菜单栏和滑动选定菜单项指示器的应用程序。 它有点工作,但我有几个问题:

  1. 最初的 state ( widthOffsetleftOffsetcolor )是硬编码的,但我需要它始终遵循活动的NavLink ,所以当我打开我的应用程序时 - 指示器立即在所选NavLink的正确位置(如果你 select 除了Home NavLink并重新加载应用程序,您将在最后一页,但指示器重置为硬编码状态)。
  2. 我没有找到从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;

升级版:

我设法解决了一些问题,使用NavLinkisActive ,现在指示器总是在适当的位置,但仍然有点麻烦:

  1. 我正在使用onClick ,这会破坏 state 和 React 的重新渲染能力。 当我更改选定的链接时,我没有找到一种方法来切换useEffect以重新呈现指示器。 此外,当我尝试不直接更改 state onClick ,但运行setCurrentPage()它工作 1/2 次,导致onClick发生更胖,而不是类。
  2. 如果您按下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

  1. 将您的 class 名称更改为is-active
  className="nav-item"
  activeClassName="is-active"
  1. 添加对链接的引用并获取活动链接(此代码可以更好)
  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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM