如何将prop传递给基于状态返回的组件?

时间:2018-01-19 11:51:21

标签: javascript reactjs

我正在尝试根据onClick处理程序this.showComponentToRender('features')上传递的参数返回一个组件。如果点击了功能,则会运行showComponentToRender(name)并设置状态,而在render()中,{this.state.showComponent}会显示正确的组件。

但是,当我尝试在

中传递道具resetFeatures={this.props.resetFeatures}时,会出现问题
showFeatures() {
    return (<FeaturesList
             updateCad={this.props.updateCad}
             resetFeatures={this.props.resetFeatures}
           />);
  }

单击RESET A4链接,调用resetCrossbow(),激活父组件中的功能。父组件更新其状态,并将状态作为prop传递给其子组件。

出于某种原因,如果我在一个设置为状态的函数中返回它,我无法让resetFeatures prop进入<FeaturesList />组件。为什么是这样?我正在寻找修复建议。

如果我采用传统的方法将<FeaturesList />置于render()的回复范围内,一切都很顺利。

这是组件

import React, { Component } from 'react';
import FeaturesList from  './FeaturesList';
import ColorsList from './ColorsList';
import './../assets/css/features-menu.css';

export default class FeaturesMenu extends Component {

  constructor(props) {
    super(props);

    this.state = {
      showComponent: this.showFeatures()
    };

    this.showFeatures = this.showFeatures.bind(this);
    this.showColors = this.showColors.bind(this);
  }

  showFeatures() {
    return (<FeaturesList
             updateCad={this.props.updateCad}
             resetFeatures={this.props.resetFeatures}
           />);
  }

  showColors() {
    this.props.resetCrossbow();
    return <ColorsList switchColor={this.props.switchColor} />
  }

  showComponentToRender(name) {
    if (name === 'features') {
      this.setState({
        showComponent: this.showFeatures()
      });
    } else {
      this.setState({
        showComponent: this.showColors()
      })
    }
  }

  render() {
    // console.log(`this.props.resetFeatures: ${this.props.resetFeatures}`);

    return (
      <div id="features-menu-wrapper">
        <nav id="features-menu">
          <li onClick={() => this.showComponentToRender('features')}>FEATURES</li>
          <li onClick={() => this.showComponentToRender('colors')}>COLORS</li>
          <li onClick={() => this.props.resetCrossbow()}>RESET A4</li>
        </nav>

        <div id="component-wrapper">
          {this.state.showComponent} // <- I am not able to pass resetFeatures prop if I do it this way. Why?

          {/* <FeaturesList
             updateCad={this.props.updateCad}
             resetFeatures={this.props.resetFeatures} <- I am able to pass resetFeatures prop as normal.
           />
          <ColorsList switchColor={this.props.switchColor} /> */}

        </div>
      </div>
    );
  }

}

2 个答案:

答案 0 :(得分:0)

您不应该将整个组件保存在您所在的州。只需设置一个与之相关的字符串,当值发生变化时,FeaturesMenu会做出反应 调用该函数来呈现正确的组件。显然,这段代码可以改变,但我想我已经说明了我的观点。 =)

const FeaturesList = props => (<div>Features List</div>);
const ColorsList = props => (<div>Colors List</div>);

class FeaturesMenu extends React.Component {

  constructor(props) {
    super(props);

    this.state = {
      currentComponent: 'Features'
    };

    this.showFeatures = this.showFeatures.bind(this);
    this.showColors = this.showColors.bind(this);
  }

  showFeatures() {
    return (<FeaturesList
             updateCad={this.props.updateCad}
             resetFeatures={this.props.resetFeatures}
           />);
  }

  showColors() {
    this.props.resetCrossbow();
    return <ColorsList switchColor={this.props.switchColor} />
  }

  showComponentToRender(name) {
    this.setState({ currentComponent: name })
  }

  render() {
    return (
      <div id="features-menu-wrapper">
        <nav id="features-menu">
          <li onClick={() => this.showComponentToRender('Features')}>FEATURES</li>
          <li onClick={() => this.showComponentToRender('Colors')}>COLORS</li>
          <li onClick={() => this.props.resetCrossbow()}>RESET A4</li>
        </nav>

        <div id="component-wrapper">
          {this[`show${this.state.currentComponent}`]()}
        </div>
      </div>
    );
  }

}

// for testing purposes
const props = {
  resetCrossbow: () => {},
  switchColor: () => {},
  updateCad: () => {},
  resetFeatures: () => {}
}

ReactDOM.render(<FeaturesMenu {...props}/>, document.querySelector('main'))
<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>
<main/>

答案 1 :(得分:0)

获得结果的最简单方法是传递其他属性以呈现特定组件的功能,并使用spread将这些道具传递给渲染组件:

   
const FeaturesList = ({additional = 'Empty'} = {}) => <div>Feature List with additional prop <b>{additional}</b></div>
const ColorsList = ({additional = 'Empty'} = {}) => <div>Colors List with additional prop <b>{additional}</b></div>

class FeaturesMenu extends React.Component {

  constructor(props) {
    super(props);

    this.state = {
      showComponent: this.showFeatures({additional: 'Initial features'})
    };

    this.showFeatures = this.showFeatures.bind(this);
    this.showColors = this.showColors.bind(this);
  }

  showFeatures(props) {
    return (<FeaturesList
             updateCad={this.props.updateCad}
             resetFeatures={this.props.resetFeatures}
             {...props}
           />);
  }

  showColors(props) {
    this.props.resetCrossbow();
    return <ColorsList switchColor={this.props.switchColor} {...props} />
  }

  showComponentToRender(name) {
    if (name === 'features') {
      this.setState({
        showComponent: this.showFeatures({additional: 'features adds'})
      });
    } else {
      this.setState({
        showComponent: this.showColors({additional: 'colors adds'})
      })
    }
  }

  render() {
    return (
      <div id="features-menu-wrapper">
        <nav id="features-menu">
          <li onClick={() => this.showComponentToRender('features')}>FEATURES</li>
          <li onClick={() => this.showComponentToRender('colors')}>COLORS</li>
          <li onClick={() => this.props.resetCrossbow()}>RESET A4</li>
        </nav>

        <div id="component-wrapper">
          {this.state.showComponent}
        </div>
      </div>
    );
  }

}

const props = {
  resetCrossbow: () => null,
  switchColor: () => null,
  updateCad: () => null,
  resetFeatures: () => null
}

ReactDOM.render(<FeaturesMenu {...props}/>, document.querySelector('root'))
<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>
<root/>