【问题标题】:React Only return props.childrenReact 只返回 props.children
【发布时间】:2016-08-24 22:11:44
【问题描述】:

全部:

我对 React 很陌生,我想知道如何在不添加任何元素(仅用于处理一些数据)的情况下构建仅逻辑组件,例如:

class LogicCom extends Component {
    constructor(props){super(props);this.props = props;}
    render(){
        return (
            {this.props.children}
        )
    }
}

【问题讨论】:

  • 请注意,return ({this.props.children}) 是无效的 JavaScript。 {this.props.children} 不是有效的对象文字。也许你在考虑 JSX,例如<div>{....}</div>。在这里,{...} 有不同的语义,但在你的代码中没有 JSX。

标签: reactjs


【解决方案1】:

编辑 在 React v16+ 中,您可以从组件返回字符串和数组。因此,组件简单地返回其子级是完全有效的......

render() {
  return this.props.children
}

docs 中了解更多信息。

原始答案

如果只有一个孩子(并且您修复了语法错误),您所拥有的将起作用。但是,children 可以是一个包含许多孩子的数组,并且您不能在 render 函数中返回一个数组。所以,你必须做两件事之一......

  1. 强制您的组件只接受带有React.Children...的单个子组件...
class LogicCom extends Component {
    render(){
        // this will throw if there are many children
        return React.Children.only(this.props.children)
    }
}
  1. 将子组件包装在另一个组件中...
class LogicCom extends Component {
    render(){
        return <div>{ this.props.children }</div>
    }
}

【讨论】:

  • 好的,所以基本上必须有一些额外的&lt;div&gt;,这通常是不可避免的?
  • 请致电React.Children.only()。就像你说的,只要只有一个孩子,这应该可行。如果有多个孩子,则必须将它们包装起来。
  • @Kuan 如果您的组件接受多个子组件,则必须有一些额外的&lt;div&gt;。如果它只接受一个孩子,请使用上面的#1,您不需要额外的&lt;div&gt;
  • 我猜你可以根据实时有多少孩子有条件地做#1或#2:P
  • 还有return &lt;&gt;{ this.props.children }&lt;/&gt;。这不会产生任何 DOM 元素。
【解决方案2】:

React 组件必须有一个要渲染的根 DOM 元素。

来自the official docs

render() 方法是必需的。

当被调用时,它应该检查 this.props 和 this.state 并返回一个 单个子元素。这个子元素可以是虚拟的 本机 DOM 组件的表示形式(例如或 React.DOM.div()) 或您定义的其他复合组件 自己。

你也可以返回 null 或 false 来表示你不想要 渲染的任何东西。在幕后,React 渲染一个标签 使用我们当前的差异算法。当返回 null 或 false,ReactDOM.findDOMNode(this) 将返回 null。

在您的情况下,这很简单——只需将您的 this.props.children 包装在某种外部元素中即可。

render(){
    return (
        <div>{this.props.children}</div>
    )
}

【讨论】:

  • 好的,谢谢。但是我想知道 react-router 是如何实现的,当我在 中包含路由时,我在页面上获得的唯一元素似乎只是我的组件,没有额外的路由器元素
  • @Kuan 你确定吗?
  • 对不起,我不太确定,我记得没有添加元素
【解决方案3】:

可以只返回子级而不包装子级。技巧是创建一个包装器 component 然后将 children 修改为一个数组,这是 React 所需要的。

Wrapper.js

import React, { Component } from 'react';

export default class extends Component {
  render() {
    return React.Children.toArray(this.props.children);
  }
}

现在您可以简单地在这个包装器组件中包装其他任何东西。

<Wrapper>
  <h1>Hello, world!</h1>
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed semper odio nec semper suscipit.</p>
</Wrapper>

现在包装器内的元素无需将其包装在 DIV 中即可呈现。

【讨论】:

    【解决方案4】:

    你可以用 React.Fragment 组件包裹你的孩子

    class LogicCom extends Component {
        constructor(props){super(props);this.props = props;}
        render(){
            return <>{children}</>
           // or return <React.Fragment>{children}</React.Fragment> it's the same
        }
    }
    

    【讨论】:

      【解决方案5】:

      作为JCD stated,渲染必须返回单个根子节点或null。还有其他几个选项:

      如果LogicCom 不需要向下传递数据,它可以用作叶子。

      <Parent>
        <LogicCom />
        {/* other children */}
      </Parent>
      

      如果您确实需要向下传递数据(例如 LogicCom 操作其传入的 props 或生成新的 props),您可以按照 @Charlie's response 中的描述要求一个子节点(进一步记录在 propTypes 中):

      class LogicCom extends Component {
          render(){
              // this will throw if there are many children
              return React.Children.only(this.props.children)
          }
      }
      
      LogicCom.propTypes = {
          children: React.PropTypes.element
      };
      

      或者使用高阶组件构造来包装另一个组件:

      const LogicCom = function (Wrapped) {
          return class extends Component {
            render () {
                // forward received props and override/add as needed
                <Wrapped {...this.props} />
            }
          }
      };
      
      // usage elsewhere: WrappedComponent will receive whatever props LogicCom
      // receives + overrides/adds.
      const WrappedComponent = LogicCom(AnotherComponent);
      

      【讨论】:

        【解决方案6】:

        Functional component 可以简单地返回 children 属性,原样

        const Wrapper = ({children}) => children
        
        ReactDOM.render(<Wrapper>123</Wrapper>, document.body)
        <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

        【讨论】:

          猜你喜欢
          • 2015-12-16
          • 1970-01-01
          • 2017-08-28
          • 2018-07-15
          • 2020-12-30
          • 2019-12-02
          • 1970-01-01
          • 1970-01-01
          • 2021-08-04
          相关资源
          最近更新 更多