【问题标题】:How to Change a css property based on a state of another component如何根据另一个组件的状态更改 css 属性
【发布时间】:2019-12-23 15:06:06
【问题描述】:

我正在用基于反应的 gatsby 构建一个网页,我需要我的导航组件将他的粘性位置更改为相对或自动,每次我打开画廊组件的模式时......但我没有不知道如何接近和解决问题。 nav 组件属于 layout 组件,它是 Gallery 的父组件...这里是涉及的组件:

导航组件:

import React, { Component } from 'react'
import { Location } from '@reach/router'
import { Link } from 'gatsby'
import { Menu, X } from 'react-feather'
import Logo from './Logo'

import './Nav.css'

export class Navigation extends Component {
  state = {
    active: false,
    activeSubNav: false,
    currentPath: false
  }

  componentDidMount = () =>
    this.setState({ currentPath: this.props.location.pathname })

  handleMenuToggle = () => this.setState({ active: !this.state.active })

  // Only close nav if it is open
  handleLinkClick = () => this.state.active && this.handleMenuToggle()

  toggleSubNav = subNav =>
    this.setState({
      activeSubNav: this.state.activeSubNav === subNav ? false : subNav
    })

  render() {
    const { active } = this.state,
    { subNav } = this.props,
      NavLink = ({ to, className, children, ...props }) => (
        <Link
          to={to}
          className={`NavLink ${
            to === this.state.currentPath ? 'active' : ''
          } ${className}`}
          onClick={this.handleLinkClick}
          {...props}
        >
          {children}
        </Link>
      )

    return (
      <nav className={`Nav ${active ? 'Nav-active' : ''}`}>

        <div className="Nav--Container container">
             <Link to="/" onClick={this.handleLinkClick}>
                <div style={{ width: `40px`, margin:`0 20px`}}>
                   <Logo />
                </div>
             </Link>

          <div className="Nav--Links">
          <NavLink to="/">Home</NavLink>
          <NavLink to="/contact/">Contacto</NavLink>

            <div className={`Nav--Group ${this.state.activeSubNav === 'about' ? 'active' : '' }`} > 

                 <span className={`NavLink Nav--GroupParent ${
                   this.props.location.pathname.includes('about') ||
                   this.props.location.pathname.includes('team') ||
                   this.props.location.pathname.includes('news') 
                   ? 'active'
                    : ''
                 }`} 
                       onClick={() => this.toggleSubNav('about')}
                 >
                     Nosotros
                 </span>
                 <div className="Nav--GroupLinks">
                    {subNav.map( (link, index)=> (
                        <NavLink 
                        to={link.link} 
                        key={'posts-subnav-link-' + index}
                        className="Nav--GroupLink">{link.name}</NavLink>
                    ))}
                 </div>

            </div>

          </div>

          <button
            className="Button-blank Nav--MenuButton"
            onClick={this.handleMenuToggle}
          >
            {active ? <X /> : <Menu />}
          </button>

        </div>

      </nav>
    )
  }
}

export default ({ subNav }) => (
  <Location>{route => <Navigation subNav={subNav} {...route} />}</Location>
)


默认位置属性在 nav.css 文件中设置为粘性我想删除它并更改它 根据模态库状态动态地打开或关闭。

这是我的画廊组件:

import React, { useState, useCallback } from "react";
import Gallery from "react-photo-gallery";
import Carousel, { Modal, ModalGateway } from "react-images";

const PhotoGallery = ({photos}) => {
  const [currentImage, setCurrentImage] = useState(0);
  const [viewerIsOpen, setViewerIsOpen] = useState(false);

  const openLightbox = useCallback((event, { photo, index }) => {
    setCurrentImage(index);
    setViewerIsOpen(true);
  }, []);

  const closeLightbox = () => {
    setCurrentImage(0);
    setViewerIsOpen(false);
  };

   return(
     <div>
         <Gallery photos={photos} onClick={openLightbox} />
            <ModalGateway>
                {viewerIsOpen ? (
                   <Modal onClose={closeLightbox}>
                   <Carousel
                    currentIndex={currentImage}
                    views={photos.map(x => ({
                    ...x,
                    srcset: x.srcSet,
                    caption: x.title
                  }))}
            />
          </Modal>
        ) : null}
      </ModalGateway>
     </div>
   )
}

export default PhotoGallery

问题是,当模式打开时,导航仍然很粘,并且不允许我访问模式控件,例如关闭和展开...我需要更改它。

【问题讨论】:

  • 导航组件是从哪里导入的?也许您应该将 viewerIsOpen 参数传递给导航组件并在 componentDidUpdate 方法中侦听它,并在 state 中保留一些 css 类信息并在 viewerIsOpen 参数上更改类名。你可以使用类名来做到这一点。
  • 我将 Nav 组件导入到 Layout 组件中...然后我将每个页面中的 Layout 用作普通标签..在 Layout 中我放置了 Gallery 组件
  • 感谢您记住我这个问题,已解决。我使用选项 2 通过样式道具分配样式。问候!

标签: javascript reactjs gatsby


【解决方案1】:

有几种方法可以解决这个问题。

  1. 旧学校类名切换

    将 prop 向下传递给反映状态的子组件。在孩子身上,使用该道具有条件地渲染一个或多个代表所需演示的类。

  2. 通过style prop 分配样式

    这类似于#1,但消除了抽象层。无需组装类列表,您只需组装要作为对象应用的 CSS 样式。

    const Component = ({ someState }) => 
      <div style={someState ? { border: "5px solid red" } : { color: "#999" }}>
        Some Text
      </div>
    
  3. 使用 CSS-in-JS 库

    上述方法的缺点是您最终会为页面上的每个元素实例复制样式。 CSS-in-JS 库通过将您的样式提取到自动生成的类中并将该类应用到您的组件来解决这个问题。我更喜欢Emotion,但还有其他人。

    使用 Emotion,您可以接受来自父级的 className 属性,该属性会覆盖子级设置的默认值。这种控制反转非常强大,解决了早期 CSS-in-JS 方法的许多缺点。

    const ParentComponent = () => {
      const [someState] = useState(false)
      return <ChildComponent css={{ color: someState ? "blue" : "red" }} />
    }
    
    const ChildComponent = ({ className }) =>
      <div
        css={{
          color: "#000",
          border: "4px solid currentColor"
        }}
        className={className}
      >
        Some Text
      </div>
    

    在上面的示例中,className 是由 Emotion 使用生成的类名分配的,该类名是根据传递给 ParentComponent 内部的 ChildComponentcss 属性分配的。当someStatefalse(默认值)时,其结果将是带有蓝色边框和蓝色文本的div。当someState 切换为true 时,边框和文字会变成红色。这是因为在 Emotion 中通过className 传入的样式会覆盖直接通过css 指定的样式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-21
    • 1970-01-01
    • 2022-01-16
    • 1970-01-01
    • 2013-12-03
    • 2017-11-27
    • 2021-10-18
    • 1970-01-01
    相关资源
    最近更新 更多