我有一个自定义组件Foo
,其bar
'功能我想从外面触发:
class Foo extends React.Component {
bar() { ... }
}
我正在呈现Foo
以及button
,其目的是触发Foo.bar()
:
render() {
return (
<Foo ...>
</Foo>
<Button onClick={I want to trigger Foo.bar()} />
);
}
我尝试过的事情:
<Button >
内移动Foo
,然后在onClick
构造函数中添加<Button/>
Foo's
- onClick的绑定无效 - 我看到它已附加,但<Button />
仍未触发onClick
。 (或者,如果它可以工作,如何正确地做到这一点)?不能做我想做的解决方案:
我看到一个potential solution建议收听整个MyComponent
中的点击,然后进行一些DOM查询以查找是否点击了实际按钮。但是,这对我来说不起作用,因为MyComponent
不拥有这些按钮(这些按钮不是MyComponent.props.children
),我更喜欢头脑风暴一个解决方案,不会迫使我必须移动按钮。
Another potential solution无效:我无法让render()
将<MyComponent />
的值返回到var myComp
,然后放入<Button onClick={() => {myComp.blah()}} />
因为<Button />
本身作为一个孩子在<MyComponent />
内实例化! (并且,它们都在相同的render()调用中)
部分b)#2(上面),使用React-Component静态类方法,也不会工作:我需要基于每个实例。
Using app state (such as a store)不是我想要的 - 或者MyComponent
是一个可重复使用的小部件,不能绑定到特定的应用程序状态或听取任何特定的商店或商店行动。
有什么建议吗?
由于
答案 0 :(得分:12)
您可以在父级上定义一个函数,该函数具有对Foo子级的引用。该函数将调用this.refs.foo.yourFunction();然后将该函数传递给按钮,这样当单击该按钮时,将调用父函数。在这里添加了一个示例,单击按钮将切换Foo组件的状态(但它可以执行任何操作)。
以下示例
class Parent extends React.Component {
triggerFoo() {
this.foo.toggle();
}
render() {
return (
<div>
<Foo ref={foo => this.foo = foo} />
<Button onClick={this.triggerFoo.bind(this)}/>
</div>
);
}
}
class Foo extends React.Component {
state = {foo: false}
toggle() {
this.setState({
foo: !this.state.foo
});
}
render() {
return (
<div>
Foo Triggered: {this.state.foo.toString()}
</div>
);
}
}
class Button extends React.Component {
render() {
return (
<button onClick={this.props.onClick}>
Click This
</button>
);
};
}
ReactDOM.render(<Parent />, document.getElementById('root'));
<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="root" />
答案 1 :(得分:2)
2020更新
这是使用功能组件和TS的方法
CSB https://codesandbox.io/s/triggering-component-method-from-another-component-skt8o?file=/src/App.tsx
上面的代码沙盒并不总是有效,但是我注意到它在一段时间后开始起作用。
import React from "react";
import "./styles.css";
import Button, { ButtonProps } from "@material-ui/core/Button";
export default function App() {
const [customRef, setCustomRef] = React.useState<HTMLButtonElement | null>(
null
);
return (
<div className="App">
<h3>
React - Triggering a component method from another component, both
belonging in the same render()
</h3>
<p>
<ClickDiv customRef={customRef} />
</p>
<CustomComponent setCustomRef={setCustomRef} />
</div>
);
}
type Props = {
setCustomRef: React.Dispatch<React.SetStateAction<HTMLButtonElement | null>>;
};
const CustomComponent = ({ setCustomRef }: Props) => {
const anchorRef = React.useRef<HTMLButtonElement>(null);
const { current } = anchorRef;
React.useEffect(() => {
if (current) {
setCustomRef(current);
}
}, [current, setCustomRef]);
return <CustomButton ref={anchorRef}>Custom Button</CustomButton>;
};
const CustomButton = React.forwardRef<HTMLButtonElement, ButtonProps>(
(props, ref) => {
const onClick = () => {
alert("CustomButton clicked");
};
return (
<Button ref={ref} {...props} variant="contained" onClick={onClick} />
);
}
);
type ClickDivProps = {
customRef: HTMLButtonElement | null;
};
const ClickDiv = ({ customRef }: ClickDivProps) => {
const onClick = () => {
if (customRef) customRef.click();
};
return <button onClick={onClick}>Triger Custom Button Click</button>;
};