我想从React Element的实例调用React组件公开的方法。
例如,在此jsfiddle https://jsfiddle.net/r6r8cp3z/中,我想从alertMessage
引用中调用HelloElement
方法。
有没有办法实现这一点而无需编写额外的包装器?
编辑 (从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')
);
答案 0 :(得分:46)
有两种方法可以访问内部函数。一个是实例级,就像你想要的那样,是另一个静态级别。
您需要在React.render
返回时调用该函数。见下文。
看看ReactJS Statics。但请注意,静态函数无法访问实例级数据,因此this
将为undefined
。
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'));
然后执行HelloRendered.alertMessage()
。
答案 1 :(得分:16)
我做过这样的事情:
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})
}
}
然后在其他地方:
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')
}
}
我没有测试过这个确切的代码,但这与我在我的项目中所做的一致,并且它运行良好:)。当然这是一个不好的例子,你应该只使用道具,但在我的情况下,子组件做了一个API调用,我想保留在该组件内。在这种情况下,这是一个很好的解决方案。
答案 2 :(得分:15)
你可以这样做
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;
现在,您可以从此组件的外部调用,如下所示
window.helloComponent.alertMessage();
答案 3 :(得分:5)
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>
</>
)
}
祝你好运...
答案 4 :(得分:3)
使用render
方法可能会弃用返回的值,建议的方法是将回调引用附加到根元素。像这样:
ReactDOM.render( <Hello name="World" ref={(element) => {window.helloComponent = element}}/>, document.getElementById('container'));
然后我们可以使用window.helloComponent访问它,并且可以使用window.helloComponent.METHOD访问它的任何方法。
以下是一个完整的例子:
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>
答案 5 :(得分:2)
您可以使用函数(onClick
是React自己的onClick
实现)向div添加onClick
处理程序,然后您可以在{ }
卷内访问该属性大括号和警报信息将会出现。
如果您希望定义可在组件类上调用的静态方法,则应使用静态。虽然:
“此块中定义的方法是静态的,这意味着您可以在创建任何组件实例之前运行它们,并且这些方法无法访问组件的道具或状态。如果要检查道具的值在静态方法中,让调用者将props作为静态方法的参数传递。“ (source)
一些示例代码:
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);
希望这会对你有所帮助,因为我不知道我是否理解你的问题,所以如果我解释错了,请纠正我:)
答案 6 :(得分:2)
似乎不推荐使用静态,而使用render
公开某些函数的其他方法似乎很复杂。与此同时,this Stack Overflow answer about debugging React虽然看似黑客,却为我做了这份工作。
答案 7 :(得分:2)
如果您在ES6中,只需使用&#34;静态&#34;您示例中的方法关键字如下:static alertMessage: function() {
...
},
希望可以帮助那里的任何人:)
答案 8 :(得分:1)
我使用此辅助方法来渲染组件并返回组件实例。 可以在该实例上调用方法。
/**
* Send netlink message and check & extend header values as needed.
* @arg sk Netlink socket.
* @arg msg Netlink message to be sent.
*
* Checks the netlink message \c nlh for completness and extends it
* as required before sending it out. Checked fields include pid,
* sequence nr, and flags.
*
* @see nl_send()
* @return Number of characters sent or a negative error code.
*/
int nl_send_auto_complete(struct nl_sock *sk, struct nl_msg *msg)
{
struct nlmsghdr *nlh;
struct nl_cb *cb = sk->s_cb;
nlh = nlmsg_hdr(msg);
if (nlh->nlmsg_pid == 0)
nlh->nlmsg_pid = sk->s_local.nl_pid;
if (nlh->nlmsg_seq == 0)
nlh->nlmsg_seq = sk->s_seq_next++;
if (msg->nm_protocol == -1)
msg->nm_protocol = sk->s_proto;
nlh->nlmsg_flags |= NLM_F_REQUEST;
if (!(sk->s_flags & NL_NO_AUTO_ACK))
nlh->nlmsg_flags |= NLM_F_ACK;
if (cb->cb_send_ow)
return cb->cb_send_ow(sk, msg);
else
return nl_send(sk, msg);
}
答案 9 :(得分:1)
在 React17 中你可以使用 useImperativeHandle 钩子。
useImperativeHandle 自定义使用 ref 时暴露给父组件的实例值。与往常一样,在大多数情况下应该避免使用 refs 的命令式代码。 useImperativeHandle 应该与 forwardRef 一起使用:
function FancyInput(props, ref) {
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
}
}));
return <input ref={inputRef} ... />;
}
FancyInput = forwardRef(FancyInput);
在这个例子中,渲染的父组件将能够调用 inputRef.current.focus()。
答案 10 :(得分:0)
docker import myapp.tar.gz myapp:latest
您可以使用class AppProvider extends Component {
constructor() {
super();
window.alertMessage = this.alertMessage.bind(this);
}
alertMessage() {
console.log('Hello World');
}
}
从窗口调用此方法。
答案 11 :(得分:0)
方法1 col_metaData[col_metaData$b %in% inputList,]$sample
:
using ChildRef
方法2: 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>
using window register
答案 12 :(得分:0)
对于这个问题,我有两个答案:
1-将您的函数用作静态方法:
statics: {
alertMessage: function () {
console.log('Method One');
}
},
但是此方法有一个大问题,因为在静态方法中您无权访问this
,并且在您要使用this
的情况下此方法不起作用,因此在这种情况下,请使用方法2。
2-首先进入您的class
:
constructor(props){
super(props);
window.alertMessage = this.alertMessage.bind(this);
}
alertMessage () {
console.log('Method Two');
}
然后在每个组件中都可以使用以下命令:
答案 13 :(得分:0)
对于动态组件,我使用了带有 props 的 getDerivedStateFromProps 方法。
您可以创建更新子组件 props 的函数,子组件中的 getDerivedStateFromProps 将为您处理 props 的更新。 例如:
class Parent extends React.Component
{
constructor(props)
{
super(props);
this.state = { selectMachine: '1' };
this.setComponent = null;
}
handleMachineChange = (e) =>{
this.setState({selectMachine: e.target.value})
}
}
class Child extends React.Component
{
state = {
programForm: {
machine_id: '1',
}
}
constructor(props)
{
super(props);
}
static getDerivedStateFromProps(props, state) {
if(props.selectMachine !== state.programForm.machine_id){
//Change in props
return{
programForm: { ...state.programForm, machine_id: props.selectMachine }
};
}
return null; // No change to state
}
}