J'ai deux composants.
J'essayais d'appeler la méthode de l'enfant de Parent, j'ai essayé de cette façon mais je n'ai pas pu obtenir de résultat
class Parent extends Component {
render() {
return (
<Child>
<button onClick={Child.getAlert()}>Click</button>
</Child>
);
}
}
class Child extends Component {
getAlert() {
alert('clicked');
}
render() {
return (
<h1 ref="hello">Hello</h1>
);
}
}
Existe-t-il un moyen d'appeler la méthode de l'enfant de la part du parent?
Remarque: les composants enfant et parent sont dans deux fichiers différents.
Tout d’abord, laissez-moi vous dire que c’est généralement le non le moyen de faire les choses dans le pays React. Habituellement, ce que vous voulez faire est de transmettre la fonctionnalité aux enfants des accessoires, et de transmettre les notifications des enfants dans les événements.
Mais si vous devez exposer une méthode impérative sur un composant enfant, vous pouvez utiliser refs . Rappelez-vous qu'il s'agit d'une trappe d'évacuation et indique généralement qu'une meilleure conception est disponible.
Auparavant, les références n'étaient prises en charge que pour les composants basés sur des classes. Avec l'avènement de React Hooks , ce n'est plus le cas
>= [email protected]
)import React, { forwardRef, useRef, useImperativeHandle } from 'react';
// We need to wrap component in `forwardRef` in order to gain
// access to the ref object that is assigned using the `ref` prop.
// This ref is passed as the second parameter to the function component.
const Child = forwardRef((props, ref) => {
// The component instance will be extended
// with whatever you return from the callback passed
// as the second argument
useImperativeHandle(ref, () => ({
getAlert() {
alert("getAlert from Child");
}
}));
return <h1>Hi</h1>;
});
const Parent = () => {
// In order to gain access to the child component instance,
// you need to assign it to a `ref`, so we call `useRef()` to get one
const childRef = useRef();
return (
<div>
<Child ref={childRef} />
<button onClick={() => childRef.current.getAlert()}>Click</button>
</div>
);
};
La documentation pour useImperativeHandle()
est ici :
useImperativeHandle
personnalise la valeur d'instance exposée aux composants parents lors de l'utilisation deref
.
class Parent extends Component {
constructor(props) {
super(props);
this.child = React.createRef();
}
onClick = () => {
this.child.current.getAlert();
};
render() {
return (
<div>
<Child ref={this.child} />
<button onClick={this.onClick}>Click</button>
</div>
);
}
}
class Child extends Component {
getAlert() {
alert('getAlert from Child');
}
render() {
return <h1>Hello</h1>;
}
}
ReactDOM.render(<Parent />, document.getElementById('root'));
<= [email protected]
)Pour des raisons historiques, voici le style basé sur les rappels que vous utiliseriez avec les versions de React antérieures à 16.3:
const { Component } = React;
const { render } = ReactDOM;
class Parent extends Component {
render() {
return (
<div>
<Child ref={instance => { this.child = instance; }} />
<button onClick={() => { this.child.getAlert(); }}>Click</button>
</div>
);
}
}
class Child extends Component {
getAlert() {
alert('clicked');
}
render() {
return (
<h1>Hello</h1>
);
}
}
render(
<Parent />,
document.getElementById('app')
);
<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>
<div id="app"></div>
Vous pouvez utiliser un autre motif ici:
class Parent extends Component {
render() {
return (
<div>
<Child setClick={click => this.clickChild = click}/>
<button onClick={() => this.clickChild()}>Click</button>
</div>
);
}
}
class Child extends Component {
constructor(props) {
super(props);
this.getAlert = this.getAlert.bind(this);
}
componentDidMount() {
this.props.setClick(this.getAlert);
}
getAlert() {
alert('clicked');
}
render() {
return (
<h1 ref="hello">Hello</h1>
);
}
}
Cela permet de définir la méthode clickChild du parent lorsque l'enfant est monté. De cette façon, lorsque vous cliquerez sur le bouton dans parent, il appellera clickChild qui appellera getAlert de l'enfant.
Cela fonctionne aussi si votre enfant est entouré de connect (), vous n'avez donc pas besoin du hack getWrappedInstance ().
Notez que vous ne pouvez pas utiliser onClick = {this.clickChild} dans parent car lorsque parent est rendu, l'enfant n'est pas monté, donc this.clickChild n'est pas encore affecté. Utiliser onClick = {() => this.clickChild ()} est acceptable car lorsque vous cliquez sur le bouton, this.clickChild doit déjà être attribué.
https://facebook.github.io/react/tips/expose-component-functions.html pour plus de réponses, réf ici Méthodes d'appel sur les composants enfants React
En examinant les références du composant "raison", vous rompez l’encapsulation et vous empêche de le refactoriser sans un examen minutieux de tous les endroits où il a été utilisé. Pour cette raison, nous recommandons fortement de traiter les références comme des données privées à un composant, un peu comme dans l'état.
En général, les données doivent être transmises dans l'arbre via des accessoires. Il y a quelques exceptions à cela (comme appeler .focus () ou déclencher une animation ponctuelle qui ne "change" pas vraiment l'état), mais chaque fois que vous exposez une méthode appelée "set", les accessoires sont généralement utilisés. un meilleur choix. Essayez de faire en sorte que le composant d'entrée interne s'inquiète de sa taille et de son apparence afin qu'aucun de ses ancêtres ne le fasse.
Nous pouvons utiliser les arbitres d'une autre manière,
Nous allons créer un élément Parent, il rendra un composant <Child/>
. Comme vous pouvez le voir, le composant qui sera rendu, vous devez ajouter l'attribut ref et lui donner un nom.
Ensuite, la fonction triggerChildAlert
, située dans la classe parente, accédera à la propriété refs du contexte suivant (lorsque la fonction triggerChildAlert
sera déclenchée, elle aura accès à la référence enfant et comportera toutes les fonctions de l'élément enfant).
class Parent extends React.Component {
triggerChildAlert(){
this.refs.child.callChildMethod();
// to get child parent returned value-
// this.value = this.refs.child.callChildMethod();
// alert('Returned value- '+this.value);
}
render() {
return (
<div>
{/* Note that you need to give a value to the ref parameter, in this case child*/}
<Child ref="child" />
<button onClick={this.triggerChildAlert}>Click</button>
</div>
);
}
}
Maintenant, le composant enfant, tel que théoriquement conçu précédemment, ressemblera à ceci:
class Child extends React.Component {
callChildMethod() {
alert('Hello World');
// to return some value
// return this.state.someValue;
}
render() {
return (
<h1>Hello</h1>
);
}
}
Voici le source code-
L’espoir vous aidera!
Si vous faites cela simplement parce que vous voulez que l'enfant fournisse à ses parents un trait réutilisable, vous pouvez envisager de le faire en utilisant render-props .
Cette technique bouleverse réellement la structure. La Child
enveloppe maintenant le parent, alors je l'ai renommé en AlertTrait
ci-dessous. J'ai gardé le nom Parent
pour la continuité, bien que ce ne soit plus vraiment un parent.
// Use it like this:
<AlertTrait renderComponent={Parent}/>
class AlertTrait extends Component {
// You may need to bind this function, if it is stateful
doAlert() {
alert('clicked');
}
render() {
return this.props.renderComponent(this.doAlert);
}
}
class Parent extends Component {
render() {
return (
<button onClick={this.props.doAlert}>Click</button>
);
}
}
Dans ce cas, AlertTrait fournit un ou plusieurs traits qu’il transmet comme élément de support quel que soit le composant qui lui a été attribué dans son accessoire renderComponent
.
Le parent reçoit doAlert
comme accessoire et peut l'appeler si nécessaire.
(Par souci de clarté, j’ai appelé la propriété renderComponent
dans l’exemple ci-dessus. Mais dans les documents React liés ci-dessus, ils l’appellent simplement render
.)
Le composant Trait peut rendre les éléments entourant le parent, dans sa fonction de rendu, mais il ne restitue rien à l'intérieur du parent. En réalité, il pourrait restituer des éléments à l'intérieur du parent s'il transmettait un autre accessoire (par exemple renderChild
) au parent, que ce dernier pourrait ensuite utiliser lors de sa méthode de rendu.
C'est un peu différent de ce que le PO a demandé, mais certaines personnes pourraient se retrouver ici (comme nous) parce qu'elles voulaient créer un trait réutilisable et pensaient qu'un composant enfant était un bon moyen de le faire.
Vous pouvez effectuer une inversion d'héritage (consultez-la ici: https://medium.com/@franleplant/react-higher-order-components-in-depth-cf9032ee6c3e ). De cette façon, vous avez accès à une instance du composant que vous souhaitez encapsuler (vous pourrez ainsi accéder à ses fonctions)
Je pense que le moyen le plus simple d'appeler des méthodes consiste à définir une requête sur le composant enfant. Ensuite, dès que l'enfant gère la demande, il appelle une méthode de rappel pour réinitialiser la demande.
Le mécanisme de réinitialisation est nécessaire pour pouvoir envoyer la même demande plusieurs fois l’une après l’autre.
Dans la méthode de rendu du parent:
const { request } = this.state;
return (<Child request={request} onRequestHandled={()->resetRequest()}/>);
Le parent a besoin de 2 méthodes pour communiquer avec son enfant dans 2 directions.
sendRequest() {
const request = { param: "value" };
this.setState({ request });
}
resetRequest() {
const request = null;
this.setState({ request });
}
L'enfant met à jour son état interne, en copiant la demande des accessoires.
constructor(props) {
super(props);
const { request } = props;
this.state = { request };
}
static getDerivedStateFromProps(props, state) {
const { request } = props;
if (request !== state.request ) return { request };
return null;
}
Enfin, il gère la demande et envoie la réinitialisation au parent:
componentDidMount() {
const { request } = this.state;
// todo handle request.
const { onRequestHandled } = this.props;
if (onRequestHandled != null) onRequestHandled();
}
Vous pouvez y arriver facilement de cette manière
Pas-
Depuis le composant enfant, accédez à cette variable à l'aide de props et exécutez la méthode de votre choix en utilisant une condition if.
class Child extends Component {
Method=()=>{
--Your method body--
}
render() {
return (
//check whether the variable has been updated or not
if(this.props.updateMethod){
this.Method();
}
)
}
}
class Parent extends Component {
constructor(){
this.state={
callMethod:false
}
}
render() {
return (
//update state according to your requirement
this.setState({
callMethod:true
}}
<Child updateMethod={this.state.callMethod}></Child>
);
}
}