【问题标题】:Storing an active state between siblings在兄弟姐妹之间存储活动状态
【发布时间】:2018-01-10 01:32:14
【问题描述】:

我在利用两个同级组件之间的活动状态时遇到了困难。我有 NavComponent.jsx 和 HeaderComponent.jsx,它们都呈现到 DOM 中的不同区域。

我有一个汉堡包按钮,它可以切换活动状态,因此在将菜单状态设置为活动以及导航时它会变成 X。我的任务是更改菜单的交互以在菜单打开时将内容推到一边,这意味着我需要将标题和导航拆分到 DOM 中的不同组件中。现在,当我希望它们一起工作时,活动状态彼此独立工作。

有人告诉我要使用 Redux Store,但也无法使用。

非常感谢您的帮助。

NavComponent.jsx

import React from 'react';

const Navigation = (props) => (
  <nav className={'navigation' + (props.active ? ' slide-in' : '')}>
    <ul className="nav">
      {
        props.items.map(
          (item, idx) => {
            return (
              <NavigationLink key={idx} href={item.href} text={item.text} clickHandler={props.clickHandler} />
            );
          }
        )
      }
    </ul>
  </nav>
);

export default class NavComponent extends React.Component {
  constructor (props) {
    super(props);
    this.state = {
      active: false
    };
    this.navItems = [
      {
        href: '/app/page1',
        text: 'PAGE 1'
      },
      {
        href: '/app/page2',
        text: 'PAGE 2'
      },
      {
        href: '/app/page3',
        text: 'PAGE 3'
      }
    ];
  }

  handleClick (e) {
    const viewportWidth = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
    if (viewportWidth <= 767) {
      this.setState({ active: !this.state.active });
    }
  }

  render () {
    return (
        <Navigation active={this.state.active} items={this.navItems} clickHandler={this.handleClick.bind(this)} />
    );
  }
}

HeaderComponent.jsx

import React from 'react';
import Logo from '../img/logo.png';
import Logo2x from '../img/logo@2x.png';
import Logo3x from '../img/logo@3x.png';

const HamburgerToggle = (props) => (
  <button className={'hamburger hamburger--squeeze' + (props.active ? ' is-active' : '')} onClick={props.clickHandler} type="button">
    <span className="hamburger-box">
      <span className="hamburger-inner"></span>
    </span>
  </button>
);

const BrandLogo = () => (
  <a href="/app/page1" className="logo-link">
    <img width="92" height="29" src={Logo} srcSet={Logo + ' 1x, ' + Logo2x + ' 2x, ' + Logo3x + '3x'} alt="Logo" className="logo" />
  </a>
);

export default class HeaderComponent extends React.Component {
  constructor (props) {
    super(props);
    this.state = {
      active: false
    };
  }
  handleClick (e) {
    const viewportWidth = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
    if (viewportWidth <= 767) {
      this.setState({ active: !this.state.active });
    }
  }
  render () {
    return (
      <div>
        <HamburgerToggle active={this.state.active} clickHandler={this.handleClick.bind(this)} />
        <BrandLogo />
      </div>
    );
  }
}

【问题讨论】:

  • 所以基本上你想渲染NavComponentHeaderComponent,当你在其中一个动作时,它会影响另一个的数据或状态?
  • 我会将这些组件作为子组件放到父组件中,该父组件将使用父组件的状态作为基础来负责兄弟通信......称之为 SideBar 或类似的东西。如果您对如何实现这一点一无所知,请做一个小规模的示例:创建一个名为 Parent 的类,以及另外两个名为 Brother 和 Sister 的类。您可以通过模拟简单的用户体验来测试状态通信的行为方式。然后您可以观察您可以在实际应用中实现的行为。
  • @AGE 不幸的是,父概念在这个阶段是不可能的,因为它们在 DOM/HTML 中是如何分配的。它们确实需要是两个独立的组件。我已经尝试过 parent 方法并意识到我无法将它分配到不同的位置。
  • 使用 redux store 就可以做到这一点。一个组件执行的操作将更新 store 中的新 statevalue。当这个新的statevalue 更新时,使用statevalue 的组件将重新渲染并因此更新。
  • 我同意使用商店,在@DaveBergschneider 同意不能使用父组件之前,我不会将其标记为重复,请参阅:stackoverflow.com/a/38904385

标签: javascript reactjs redux


【解决方案1】:

store.js

const defaultState = {
  headerData
};

const store = createStore(rootReducer, defaultState));

export default store;

rootReducer 这里是一个 .js 文件,所有的 reducer 都组合在一起了。

HeaderComponent.js

class HeaderComponent extends React.Component {

    constructor...

    handleClick...

    render...

}

function mapStateToProps (state) {
  return {
    headerData: state.headerData
  };
}

export default connect(mapStateToProps)(HeaderComponent);

NavComponent.js

class NavComponent extends React.Component {

    constructor...

    handleClick...

    render...

}

function mapDispatchToProps (dispatch) {
  return bindActionCreators(navActions, dispatch);
}

export default connect(mapDispatchToProps)(NavComponent);

在这种情况下,您的 NavComponent 可以访问您的文件 navActions 中的所有操作。你需要为此创建一个js文件navActions

当您在 store.js 中创建即时时,您的 HeaderComponent 已映射到商店的 headerData。您需要为此创建一个 .js 文件 headerData

NavComponent 中调用的操作触发的 reducer 将更新 store 中的 headerData,而 HeaderComponent 将在映射到它后重新渲染。

我强烈建议阅读Redux Documentation 中的Basics 的全部内容,以了解如何编写ActionsReducers

【讨论】:

  • 谢谢,这让我有了一个好的方向......实际上,由于上​​下文,我比大多数文档更了解这一点。
  • 没问题。我能给你的最好建议是学习如何正确地编写 ActionsReducers。完成后,更改商店的数据真的很容易!
  • 我还是卡住了......我以为我已经做到了......在我准备付钱给某人的时候。
  • 不要犹豫,在这篇文章中发布您遇到的错误或错误。我会尽快回复。
  • 只需说出您遇到问题的步骤以及您正在尝试做什么
猜你喜欢
  • 2017-04-23
  • 2019-05-06
  • 2020-01-31
  • 2020-06-06
  • 2021-11-19
  • 2019-12-20
  • 2023-03-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多