Quiero llamar a un método expuesto por un componente React desde la instancia de un Elemento React.
Por ejemplo, en este jsfiddle . Quiero llamar al alertMessage
método desde la HelloElement
referencia.
¿Hay alguna manera de lograr esto sin tener que escribir envoltorios adicionales?
Editar (código copiado de JSFiddle)
<div id="container"></div>
<button onclick="onButtonClick()">Click me!</button>
var onButtonClick = function () {
//call alertMessage method from the reference of a React Element! Something like HelloElement.alertMessage()
console.log("clicked!");
}
var Hello = React.createClass({displayName: 'Hello',
alertMessage: function() {
alert(this.props.name);
},
render: function() {
return React.createElement("div", null, "Hello ", this.props.name);
}
});
var HelloElement = React.createElement(Hello, {name: "World"});
React.render(
HelloElement,
document.getElementById('container')
);
Respuestas:
Hay dos formas de acceder a una función interna. Uno, nivel de instancia, como quieras, otro nivel estático.
Ejemplo
Necesita llamar a la función al regresar de
React.render
. Vea abajo.Estático
Eche un vistazo a ReactJS Statics . Sin embargo,
this
tenga en cuenta que una función estática no puede acceder a los datos a nivel de instancia, por lo que también lo seríaundefined
.var onButtonClick = function () { //call alertMessage method from the reference of a React Element! HelloRendered.alertMessage(); //call static alertMessage method from the reference of a React Class! Hello.alertMessage(); console.log("clicked!"); } var Hello = React.createClass({ displayName: 'Hello', statics: { alertMessage: function () { alert('static message'); } }, alertMessage: function () { alert(this.props.name); }, render: function () { return React.createElement("div", null, "Hello ", this.props.name); } }); var HelloElement = React.createElement(Hello, { name: "World" }); var HelloRendered = React.render(HelloElement, document.getElementById('container'));
Entonces hazlo
HelloRendered.alertMessage()
.fuente
ref
que es una función llamada con la instancia como parámetro. Esto también le permite acceder a objetos que no están en el nivel superior, por ejemplo, si está renderizando<MuiThemeProvider><Hello ref={setHelloRef} /></MuiThemeProvider>
, obtiene la referencia correcta que se pasa a susetHelloRef
función en lugar de una aMuiThemeProvider
.Puedes hacer como
import React from 'react'; class Header extends React.Component{ constructor(){ super(); window.helloComponent = this; } alertMessage(){ console.log("Called from outside"); } render(){ return ( <AppBar style={{background:'#000'}}> Hello </AppBar> ) } } export default Header;
Ahora, desde fuera de este componente, puede llamar así a continuación
window.helloComponent.alertMessage();
fuente
He hecho algo como esto:
class Cow extends React.Component { constructor (props) { super(props); this.state = {text: 'hello'}; } componentDidMount () { if (this.props.onMounted) { this.props.onMounted({ say: text => this.say(text) }); } } render () { return ( <pre> ___________________ < {this.state.text} > ------------------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || || </pre> ); } say (text) { this.setState({text: text}); } }
Y luego en otro lugar:
class Pasture extends React.Component { render () { return ( <div> <Cow onMounted={callbacks => this.cowMounted(callbacks)} /> <button onClick={() => this.changeCow()} /> </div> ); } cowMounted (callbacks) { this.cowCallbacks = callbacks; } changeCow () { this.cowCallbacks.say('moo'); } }
No he probado este código exacto, pero está en la línea de lo que hice en un proyecto mío y funciona muy bien :). Por supuesto, este es un mal ejemplo, solo debería usar accesorios para esto, pero en mi caso, el subcomponente hizo una llamada a la API que quería mantener dentro de ese componente. En tal caso, esta es una buena solución.
fuente
this.cowCallbacks.say('moo')
this
a callback (que será una instancia de Cow) en lugar decallbacks
.Con el
render
método potencialmente desaprobando el valor devuelto, el enfoque recomendado ahora es adjuntar una referencia de devolución de llamada al elemento raíz. Me gusta esto:ReactDOM.render( <Hello name="World" ref={(element) => {window.helloComponent = element}}/>, document.getElementById('container'));
al que luego podemos acceder usando window.helloComponent, y cualquiera de sus métodos se puede acceder con window.helloComponent.METHOD.
Aquí tienes un ejemplo completo:
var onButtonClick = function() { window.helloComponent.alertMessage(); } class Hello extends React.Component { alertMessage() { alert(this.props.name); } render() { return React.createElement("div", null, "Hello ", this.props.name); } }; ReactDOM.render( <Hello name="World" ref={(element) => {window.helloComponent = element}}/>, document.getElementById('container'));
<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="container"></div> <button onclick="onButtonClick()">Click me!</button>
fuente
ref={component => {this.setState({ helloComponent: component; })}}
Luego, en el controlador de clic ...this.state.helloComponent.alertMessage();
Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
y no vincula el componente a la ventanaclass AppProvider extends Component { constructor() { super(); window.alertMessage = this.alertMessage.bind(this); } alertMessage() { console.log('Hello World'); } }
Puede llamar a este método desde la ventana usando
window.alertMessage()
.fuente
Si está en ES6 simplemente use la palabra clave "estática" en su método de su ejemplo, sería la siguiente:
static alertMessage: function() { ...
},
Hope puede ayudar a cualquiera :)
fuente
Con
React hook - useRef
const MyComponent = ({myRef}) => { const handleClick = () => alert('hello world') myRef.current.handleClick = handleClick return (<button onClick={handleClick}>Original Button</button>) } MyComponent.defaultProps = { myRef: {current: {}} } const MyParentComponent = () => { const myRef = React.useRef({}) return ( <> <MyComponent myRef={myRef} /> <button onClick={myRef.current.handleClick}> Additional Button </button> </> ) }
Buena suerte...
fuente
Puede simplemente agregar un
onClick
controlador al div con la función (onClick
es la propia implementación de ReactonClick
) y puede acceder a la propiedad dentro{ }
llaves, y aparecerá su mensaje de alerta.En caso de que desee definir métodos estáticos que se pueden llamar en la clase de componente, debe utilizar estáticos. A pesar de que:
"Los métodos definidos dentro de este bloque son estáticos, lo que significa que puede ejecutarlos antes de que se creen instancias de componentes, y los métodos no tienen acceso a los accesorios o al estado de sus componentes. Si desea verificar el valor de los accesorios en un método, haga que la persona que llama pase los accesorios como un argumento para el método estático ". ( fuente )
Algún código de ejemplo:
const Hello = React.createClass({ /* The statics object allows you to define static methods that can be called on the component class. For example: */ statics: { customMethod: function(foo) { return foo === 'bar'; } }, alertMessage: function() { alert(this.props.name); }, render: function () { return ( <div onClick={this.alertMessage}> Hello {this.props.name} </div> ); } }); React.render(<Hello name={'aworld'} />, document.body);
Espero que esto te ayude un poco, porque no sé si entendí tu pregunta correctamente, así que corrígeme si la interpreté mal :)
fuente
Parece que las estáticas están en desuso y los otros métodos para exponer algunas funciones
render
parecen complicados. Mientras tanto, esta respuesta de Stack Overflow sobre la depuración de React , aunque parecía hack-y, hizo el trabajo por mí.fuente
método 1
using ChildRef
:public childRef: any = React.createRef<Hello>(); public onButtonClick= () => { console.log(this.childRef.current); // this will have your child reference } <Hello ref = { this.childRef }/> <button onclick="onButtonClick()">Click me!</button>
Método 2:
using window register
public onButtonClick= () => { console.log(window.yourRef); // this will have your child reference } <Hello ref = { (ref) => {window.yourRef = ref} }/>` <button onclick="onButtonClick()">Click me!</button>
fuente
Utilizo este método auxiliar para renderizar componentes y devolver una instancia de componente. Los métodos se pueden llamar en esa instancia.
static async renderComponentAt(componentClass, props, parentElementId){ let componentId = props.id; if(!componentId){ throw Error('Component has no id property. Please include id:"...xyz..." to component properties.'); } let parentElement = document.getElementById(parentElementId); return await new Promise((resolve, reject) => { props.ref = (component)=>{ resolve(component); }; let element = React.createElement(componentClass, props, null); ReactDOM.render(element, parentElement); }); }
fuente