【问题标题】:How to pass a prop to a component that is returned based on state?如何将道具传递给基于状态返回的组件?
【发布时间】:2018-06-28 15:48:06
【问题描述】:

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

但是,当我尝试在

中传递一个 prop resetFeatures={this.props.resetFeatures}
showFeatures() {
    return (<FeaturesList
             updateCad={this.props.updateCad}
             resetFeatures={this.props.resetFeatures}
           />);
  }

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

由于某种原因,如果我在设置为状态的函数中返回它,我无法让 resetFeatures 道具进入&lt;FeaturesList /&gt; 组件。为什么是这样?我正在寻找修复建议。

如果我按照传统方法将&lt;FeaturesList /&gt; 放在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>
    );
  }

}

【问题讨论】:

  • {this.state.showComponent} 已被渲染。所以你不能在那里改变他们的道具。您可以创建某种 HOC 并使用它将其他道具传递给 showComponent

标签: javascript reactjs


【解决方案1】:

实现结果最简单的方法是传递额外的属性来渲染特定的组件功能,并使用 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/>

【讨论】:

    【解决方案2】:

    您不应将整个组件保存在您的状态中。只需设置一个与之相关的字符串,随着值的变化,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/>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-10-08
      • 2019-11-16
      • 2020-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-07
      • 2022-12-22
      相关资源
      最近更新 更多