You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+TypeScript点击按钮更新Navbar按钮样式失败求助

问题根源

useRef的核心特性是更新其current属性不会触发组件重渲染。你修改buttonDesign.current后,组件不会重新执行渲染逻辑,所以Button的variant属性始终读取初始值,样式自然不会更新。

两种可行解决方案

方案一:改用useState管理样式状态

把useRef换成useState,因为useState的状态更新会强制组件重渲染,这样Button就能读取到最新的variant值。

修改后的代码:

import { Button, Container, Nav, Navbar as NavbarBs } from "react-bootstrap";
import { NavLink } from "react-router-dom";
import { useState } from "react";

export function Navbar() {
  const [buttonVariant, setButtonVariant] = useState("");

  const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
    const text = e.currentTarget.firstChild?.textContent;
    if (text === "Home") {
      setButtonVariant("outline-danger");
    } else if (text === "Store") {
      setButtonVariant("outline-dark");
    }
  };

  return (
    <NavbarBs
      fixed="top"
      style={{
        height: "5vh",
        position: "fixed",
        width: "100%",
        background: "transparent",
      }}
    >
      <Container>
        <Nav className="d-flex justify-content-between w-100">
          <Nav.Link to="/" as={NavLink}>
            <Button
              variant={buttonVariant}
              style={{
                outline: "none",
                padding: "5px 50px 5px 50px",
                fontFamily: "Playfair Display, serif",
                fontSize: "1rem",
              }}
              onClick={handleClick}
            >
              Home
            </Button>
          </Nav.Link>
          <Nav.Link to="/store" as={NavLink}>
            <Button
              variant={buttonVariant}
              style={{
                outline: "none",
                padding: "5px 50px 5px 50px",
                fontFamily: "Playfair Display, serif",
                fontSize: "1rem",
              }}
              onClick={handleClick}
            >
              Store
            </Button>
          </Nav.Link>
          <Nav.Link to="/about" as={NavLink}>
            <Button
              variant={buttonVariant}
              style={{
                outline: "none",
                padding: "5px 50px 5px 50px",
                fontFamily: "Playfair Display, serif",
                fontSize: "1rem",
              }}
            >
              About
            </Button>
          </Nav.Link>
        </Nav>
      </Container>
    </NavbarBs>
  );
}

方案二:利用React Router NavLink的active状态(更推荐)

你的按钮本质是路由导航链接,NavLink会在当前路由匹配时自动添加active类,完全可以利用这个特性自动切换样式,不用手动处理点击事件,更符合路由场景的最佳实践。

示例代码(根据当前路由动态切换Button variant):

import { Button, Container, Nav, Navbar as NavbarBs } from "react-bootstrap";
import { NavLink, useLocation } from "react-router-dom";

export function Navbar() {
  const location = useLocation();

  // 根据当前路由返回对应按钮的样式变体
  const getButtonVariant = (path: string) => {
    if (location.pathname === path) {
      switch(path) {
        case "/":
          return "outline-danger";
        case "/store":
          return "outline-dark";
        default:
          return "";
      }
    }
    return "";
  };

  return (
    <NavbarBs
      fixed="top"
      style={{
        height: "5vh",
        position: "fixed",
        width: "100%",
        background: "transparent",
      }}
    >
      <Container>
        <Nav className="d-flex justify-content-between w-100">
          <Nav.Link to="/" as={NavLink}>
            <Button
              variant={getButtonVariant("/")}
              style={{
                outline: "none",
                padding: "5px 50px 5px 50px",
                fontFamily: "Playfair Display, serif",
                fontSize: "1rem",
              }}
            >
              Home
            </Button>
          </Nav.Link>
          <Nav.Link to="/store" as={NavLink}>
            <Button
              variant={getButtonVariant("/store")}
              style={{
                outline: "none",
                padding: "5px 50px 5px 50px",
                fontFamily: "Playfair Display, serif",
                fontSize: "1rem",
              }}
            >
              Store
            </Button>
          </Nav.Link>
          <Nav.Link to="/about" as={NavLink}>
            <Button
              variant={getButtonVariant("/about")}
              style={{
                outline: "none",
                padding: "5px 50px 5px 50px",
                fontFamily: "Playfair Display, serif",
                fontSize: "1rem",
              }}
            >
              About
            </Button>
          </Nav.Link>
        </Nav>
      </Container>
    </NavbarBs>
  );
}

这个方案的好处是:路由切换时自动同步样式,不用维护额外的点击事件状态,逻辑更简洁可靠。

内容的提问来源于stack exchange,提问作者ether

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 20:30:51