web-dev-qa-db-fra.com

Pourquoi React.Children.only?

Question rapide pour les gourous de la réaction;)

React.Children.only est l'un de ses apis de niveau supérieur et est très couramment utilisé par react-redux (<Provider />) et React Router (<Router />) pour injecter un magasin/routeur en tant que contexte. pourquoi ne pas simplement return props.children? Semble quelque chose à faire avec JSX?

EDIT: S'il vous plaît ne pas expliquer ce que est React.Children.only, je demande pour pourquoi l'utiliser à la place de props.children, qui semble plus puissant/flexible.

11
Xlee

Comme indiqué dans la docs

Vérifie que les enfants n'ont qu'un seul enfant (un élément React) et le renvoie. Sinon, cette méthode génère une erreur.

Alors maintenant, pourquoi est-il utile d’utiliser simplement props.children?

La raison principale est qu’elle génère une erreur, ce qui stoppe l’environnement de développement dans son ensemble afin que vous ne puissiez pas le sauter.

C'est un utilitaire pratique qui crée une couche spécifique d'application de cette règle spécifique d'avoir un seul enfant.

Bien sûr, vous pouvez utiliser propTypes, mais ils ne feront que mettre en garde sur la console.

Un cas d'utilisation de React.Children.only peut consister à appliquer une interface déclarative spécifique qui devrait consister en un composant enfant logique:

class GraphEditorEditor extends React.Component {
  componentDidMount() {
    this.props.editor.makeEditable();
    // and all other editor specific logic
  }

  render() {
    return null;
  }
}

class GraphEditorPreview extends React.Component {
  componentDidMount() {
    this.props.editor.makePreviewable();
    // and all other preview specific logic
  }

  render() {
    return null;
  }
}

class GraphEditor extends React.Component {
  static Editor = GraphEditorEditor;
  static Preview = GraphEditorPreview;
  wrapperRef = React.createRef();

  state = {
    editorInitialized: false
  }

  componentDidMount() {
    // instantiate base graph to work with in logical children components
    this.editor = SomeService.createEditorInstance(this.props.config);
    this.editor.insertSelfInto(this.wrapperRef.current);

    this.setState({ editorInitialized: true });
  }

  render() {
    return (
      <div ref={this.wrapperRef}>
        {this.editorInitialized ?
          React.Children.only(
            React.cloneElement(
              this.props.children, 
              { editor: this.editor }
            )
          ) : null
        }
      </div>
    );
  }
}

qui peut être utilisé comme ceci:

class ParentContainer extends React.Component {
  render() {
    return (
      <GraphEditor config={{some: "config"}}>
        <GraphEditor.Editor> //<-- EDITOR mode
      </GraphEditor>
    )
  }
}

// OR

class ParentContainer extends React.Component {
  render() {
    return (
      <GraphEditor config={{some: "config"}}>
        <GraphEditor.Preview> //<-- Preview mode
      </GraphEditor>
    )
  }
}

J'espère que ça aide un peu.

9
Karen Grigoryan

Avant React 16 , la méthode de rendu d'un composant ne pouvait pas renvoyer un tableau d'éléments. Lors de la mise en œuvre d'un composant qui n'introduisait aucun balisage propre, vous n'aviez d'autre choix que d'accepter qu'un seul enfant:

// We have to ensure that there's only one child, because returning an array
// from a component is prohibited.
const DisplayIf = ({children, condition}, {uniforms}) =>
    condition(uniforms) ? Children.only(children) : nothing;
DisplayIf.contextTypes = BaseField.contextTypes;

Maintenant, vous pouvez simplement return props.children, obligeant l'appelant à inclure keys dans les éléments du tableau, ou return <>{props.children}</>, en utilisant un Fragment pour éviter de retourner un tableau:

const DisplayIf = ({children, condition}, {uniforms}) =>
    condition(uniforms) ? <>{children}</> : nothing;
DisplayIf.contextTypes = BaseField.contextTypes;
0
BudgieInWA