javascript - prop 更改时重新渲染功能组件

标签 javascript reactjs functional-programming

当父状态传递给子组件更改时,我在重新渲染组件时遇到问题。 MapNav 组件包含触发方法更改当前显示的弹出窗口的按钮。我的问题是当有人点击 zalogujwyloguj 时重新渲染 UserPopup 按钮,它应该可以工作,但不能,我也不知道出了什么问题。想要在 isLoggedIn 状态更改时触发动画,并且还有一件事 logIn 方法正确更改状态。 isLoggedIn 状态只是暂时的,稍后我会将其更改为使用存储。我正在尝试编写尽可能多的功能组件,但在某些情况下我无法避免使用状态,并且我打赌我的代码中存在问题,因此我将感谢所有改进提示。

const MapNav = (props) => {
  return       <div className={'mapNavContainer'}>
        <ul className={'navList'}>
          <li><a href="#about"><i className={"glyphicon glyphicon-fullscreen"} /></a></li>
          <li><a href="#about"><i className={"glyphicon glyphicon-chevron-left"} /></a></li>
          <li><a href="#about"><i className={"glyphicon glyphicon-chevron-right"} /></a></li>
          <li><a href="#about"><i className={"glyphicon glyphicon-map-marker"} /></a></li>
          <li><a href="#" onClick={props.onUserIconClick}><i className={"glyphicon glyphicon-user"} /></a></li>
          <li><a href="#" onClick={props.onInfoClick}><i className={"glyphicon glyphicon-info-sign"} /></a></li>
        </ul>
      </div>
}

const UserPopup = (props) => {
  return <div>
    {(props.isLoggedIn) ? (
      <div className={'navPopups col-sm-3 panel panel-default'}>
        <div className={"panel-heading"}>Zalogowany</div>
        <div className={"panel-body"}>
          <button type='submit' onClick={props.logIn}>wyloguj</button>
        </div>
      </div>
      ) : (
        <div className={'navPopups col-sm-3 panel panel-default'}>
          <div className={"panel-heading"}>Niezalogowany</div>
          <div className={"panel-body"}>
            <button type='submit' onClick={props.logIn}>Zaloguj</button>
          </div>
        </div>
      )
    }
  </div>;
};

function Welcome(props) {
  return <div className={'navPopups col-sm-3 panel panel-default'}>
    <div className={"panel-heading"}>Informacje o Autorze.</div>
    <div className={"panel-body"}>
        Basic panel example
    </div>
  </div>;
}

class MapHeader extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      currentPopup: null,
      isLoggedIn: false,
      username: 'gregorowicz.k@gmail.com',
    };

    this.onInfoClick = this.onInfoClick.bind(this);
    this.onUserIconClick = this.onUserIconClick.bind(this);
    this.logIn = this.logIn.bind(this);
  }

  onInfoClick = (e) => {
    e.preventDefault();
    this.setPopup(<Welcome />);
  }

  onUserIconClick = (e) => {
    e.preventDefault();
    const loginPopup = <UserPopup isLoggedIn={this.state.isLoggedIn} username={this.state.username} logIn={this.logIn} />;
    this.setPopup(loginPopup);
  }

  setPopup = (obj) => {
    this.state.currentPopup === null ? this.setState({ currentPopup: obj }) : this.setState({ currentPopup: null });
  }

  logIn = (e) => {
    this.setState({ isLoggedIn: !this.state.isLoggedIn });
  }

  render() {
    return (
      <nav className={'header'}>
        <div className={'container-fluid'}>
          <div className={"navbar-header"}>
            <button type="button" className={"navbar-toggle collapsed"} data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
              <span className={"sr-only"}>Toggle navigation</span>
              <span className={"icon-bar"} />
              <span className={"icon-bar"} />
              <span className={"icon-bar"} />
            </button>
          </div>

          <div id={"navbar"} className={'navContainer'}>
            {MapNav({onInfoClick:this.onInfoClick, onUserIconClick:this.onUserIconClick})}
    {this.state.currentPopup ? this.state.currentPopup : null}
          </div>
        </div>
      </nav>
    )
  }
}

// Render it
ReactDOM.render(
  <MapHeader />,
  document.getElementById("react")
);
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/latest/css/bootstrap.min.css" />

最佳答案

我已经解决了。我的代码中有 currentPopup 状态,它存储当前显示的弹出窗口,要查看更改,我必须在 isLogggedIn 状态更改后再次卸载并安装组件,因此我更改了显示当前弹出窗口的方式。我只存储简单的字符串值,而不是将整个组件存储在状态中,这些值提供有关当前组件的信息。无论如何,感谢您的提示,我一定会将它们应用到我的代码中。

const MapNav = (props) => {
  return       <div className={'mapNavContainer'}>
        <ul className={'navList'}>
          <li><a href="#about"><i className={"glyphicon glyphicon-fullscreen"} /></a></li>
          <li><a href="#about"><i className={"glyphicon glyphicon-chevron-left"} /></a></li>
          <li><a href="#about"><i className={"glyphicon glyphicon-chevron-right"} /></a></li>
          <li><a href="#about"><i className={"glyphicon glyphicon-map-marker"} /></a></li>
          <li><a href="#" onClick={props.onUserIconClick}><i className={"glyphicon glyphicon-user"} /></a></li>
          <li><a href="#" onClick={props.onInfoClick}><i className={"glyphicon glyphicon-info-sign"} /></a></li>
        </ul>
      </div>
}

const UserPopup = (props) => {
  return <div>
    {(props.isLoggedIn) ? (
      <div className={'navPopups col-sm-3 panel panel-default'}>
        <div className={"panel-heading"}>Zalogowany</div>
        <div className={"panel-body"}>
          <button type='submit' onClick={props.logIn}>wyloguj</button>
        </div>
      </div>
      ) : (
        <div className={'navPopups col-sm-3 panel panel-default'}>
          <div className={"panel-heading"}>Niezalogowany</div>
          <div className={"panel-body"}>
            <button type='submit' onClick={props.logIn}>Zaloguj</button>
          </div>
        </div>
      )
    }
  </div>;
};

function Welcome(props) {
  return <div className={'navPopups col-sm-3 panel panel-default'}>
    <div className={"panel-heading"}>Informacje o Autorze.</div>
    <div className={"panel-body"}>
        Basic panel example
    </div>
  </div>;
}

class MapHeader extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      currentPopup: null,
      isLoggedIn: null,
    };

    this.onInfoClick = this.onInfoClick.bind(this);
    this.onUserIconClick = this.onUserIconClick.bind(this);
    this.logIn = this.logIn.bind(this);
  }
                  
  onInfoClick = (e) => {
    e.preventDefault();
    this.setState({ currentPopup: this.state.currentPopup === 'info' ? null : 'info' });
  }
    
  onUserIconClick = (e) => {
    e.preventDefault();
    this.setState({ currentPopup: this.state.currentPopup === 'user_login' ? null : 'user_login' });
  }

  setPopup = (obj) => {
    this.setState({ currentPopup: this.state.currentPopup === 'user_login' ? null : 'user_login' });
  }

  logIn = (e) => {
    this.setState({ isLoggedIn: !this.state.isLoggedIn });
  }

  render() {
    return (
      <nav className={'header'}>
        <div className={'container-fluid'}>
          <div className={"navbar-header"}>
            <button type="button" className={"navbar-toggle collapsed"} data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
              <span className={"sr-only"}>Toggle navigation</span>
              <span className={"icon-bar"} />
              <span className={"icon-bar"} />
              <span className={"icon-bar"} />
            </button>
          </div>

          <div id={"navbar"} className={'navContainer'}>
            {MapNav({onInfoClick:this.onInfoClick, onUserIconClick:this.onUserIconClick})}

              {this.state.currentPopup === 'info' ? <Welcome /> : null}
              {this.state.currentPopup === 'user_login' ? (
                <UserPopup isLoggedIn={this.state.isLoggedIn} logIn={this.logIn} />
              ) : null}

          </div>
        </div>
      </nav>
    )
  }
}

// Render it
ReactDOM.render(
  <MapHeader />,
  document.getElementById("react")
);
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/latest/css/bootstrap.min.css" />

关于javascript - prop 更改时重新渲染功能组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42175389/

相关文章:

javascript - 多个模态只能关闭1个

javascript - 我正在尝试使用按钮在 Chrome 中使用 HTML 编辑网页的宽度和高度

javascript - jQuery 在特定元素之后按类定位表行

javascript - React - 设置状态

javascript - JavaScript 是否有像 "range()"这样的方法在提供的范围内生成范围?

javascript - 在两个函数中两次使用 console.log 时只打印一个 undefined

reactjs - 使用 Prop 值删除 useEffect Hook 中状态数组元素中的元素

javascript - 使用 React 中的下拉菜单过滤来自 API 的数据

haskell - 需要帮助重写在 OCaml(或任何 ML)中按字谜词对单词进行分组的 Haskell 程序吗?

Javascript 函数加载(通过引用?)