[javascript] 부모로부터 자식 메서드 호출
두 가지 구성 요소가 있습니다.
- 부모 구성 요소
- 하위 구성 요소
부모님으로부터 자녀의 방법을 호출하려고했지만이 방법을 시도했지만 결과를 얻을 수 없었습니다.
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>
);
}
}
부모로부터 자식 메서드를 호출하는 방법이 있습니까?
참고 : 하위 및 상위 구성 요소는 서로 다른 두 파일에 있습니다.
답변
먼저, 이것이 일반적으로 React 땅에서 물건을 다루는 방법이 아니라고 표현하겠습니다 . 일반적으로 소품으로 어린이에게 기능을 전달하고 이벤트에서 어린이의 알림을 전달하는 것이 좋습니다 dispatch
.
그러나 자식 구성 요소에 명령 적 방법을 노출 해야하는 경우 refs 를 사용할 수 있습니다 . 이것은 탈출구이며 일반적으로 더 나은 디자인을 사용할 수 있음을 나타냅니다.
이전에는 클래스 기반 구성 요소에 대해서만 참조가 지원되었습니다. React Hooks 가 등장하면서 더 이상 그렇지 않습니다.
후크 및 기능 구성 요소 사용 ( >= react@16.8
)
const { forwardRef, useRef, useImperativeHandle } = 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>
);
};
ReactDOM.render(
<Parent />,
document.getElementById('root')
);
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
<div id="root"></div>
설명서 useImperativeHandle()
는 다음과 같습니다.
useImperativeHandle
를 사용할 때 상위 구성 요소에 노출되는 인스턴스 값을 사용자 정의합니다ref
.
클래스 구성 요소 사용 ( >= react@16.4
)
const { Component } = React;
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'));
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
<div id="root"></div>
레거시 API ( <= react@16.3
)
역사적으로 16.3 이전의 React 버전에서 사용하는 콜백 기반 스타일은 다음과 같습니다.
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>
답변
여기서 다른 패턴을 사용할 수 있습니다.
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>
);
}
}
clickChild
자식이 마운트 될 때 부모의 방법 을 설정하는 것입니다. 이런 식으로 부모의 버튼을 클릭하면 clickChild
child ‘s를 호출합니다 getAlert
.
이것은 자녀가 포장되어 해킹이 connect()
필요하지 않은 경우에도 작동합니다 getWrappedInstance()
.
onClick={this.clickChild}
부모가 렌더링 될 때 자식이 마운트 this.clickChild
되지 않았으므로 아직 할당되지 않았 으므로 부모에서 사용할 수 없습니다 . onClick={() => this.clickChild()}
버튼을 클릭하면 this.clickChild
이미 할당되어 있어야 하기 때문에 사용하는 것이 좋습니다.
답변
https://facebook.github.io/react/tips/expose-component-functions.html
자세한 답변은 여기를 참조하십시오 React 하위 구성 요소에 대한 메소드 호출
“이유”구성 요소의 참조를 살펴보면 캡슐화가 깨지고 사용 된 모든 위치를 신중하게 검사하지 않고 해당 구성 요소를 리팩터링 할 수 없습니다. 이 때문에 ref는 상태와 매우 유사하게 구성 요소에 대한 비공개로 처리하는 것이 좋습니다.
일반적으로 데이터는 소품을 통해 트리로 전달되어야합니다. 이에 대한 몇 가지 예외가 있습니다 (예 : .focus () 호출 또는 상태를 실제로 “변경”하지 않는 일회성 애니메이션 트리거). “set”이라는 메서드를 노출 할 때마다 소품은 일반적으로 더 나은 선택입니다. 내부 입력 구성 요소가 크기와 모양에 대해 걱정하여 조상이 처리하지 않도록하십시오.
답변
useEffect를 사용한 대체 방법 :
부모의:
const [refresh, doRefresh] = useState(0);
<Button onClick={()=>doRefresh(refresh+1)} />
<Children refresh={refresh} />
어린이:
useEffect(() => {
refresh(); //children function of interest
}, [props.refresh]);
답변
다른 방법으로 심판을 사용할 수 있습니다.
Parent 요소를 만들려고합니다 <Child/>
. 구성 요소 를 렌더링합니다 . 보다시피, 렌더링 될 컴포넌트는 ref 속성 을 추가하고 그 이름을 제공해야합니다.
그런 다음 triggerChildAlert
부모 클래스에있는 triggerChildAlert
함수는 이 컨텍스트의 refs 속성에 액세스합니다 ( 함수가 트리거되면 자식 참조에 액세스하고 자식 요소의 모든 기능을 갖습니다).
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>
);
}
}
이제 이론적으로 이전에 설계된 하위 구성 요소는 다음과 같습니다.
class Child extends React.Component {
callChildMethod() {
alert('Hello World');
// to return some value
// return this.state.someValue;
}
render() {
return (
<h1>Hello</h1>
);
}
}
답변
Child가 재사용 가능한 특성을 부모에게 제공하기를 원하기 때문에이 작업을 수행하는 경우 render-props 를 사용하여 수행하는 것을 고려할 수 있습니다. 대신 좋습니다.
이 기술은 실제로 구조를 거꾸로 뒤집습니다. 는 Child
내가로 이름을 바꾼 그래서 지금, 부모를 감싸고 AlertTrait
아래. 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>
);
}
}
이 경우, AlertTrait은 하나 이상의 특성을 제공하며, 이는 특성에 제공된 구성 요소에 대한 특성으로 소품으로 전달됩니다 renderComponent
.
부모는 doAlert
소품으로 받고 필요할 때 전화를 걸 수 있습니다.
(명확하게하기 renderComponent
위해 위 예제에서 prop 을 호출했지만 위의 React docs에서는 그냥 호출했습니다 render
.)
Trait 컴포넌트는 렌더링 기능에서 부모를 둘러싼 물건을 렌더링 할 수 있지만 부모 내부에는 아무것도 렌더링하지 않습니다. 실제로 다른 소품을 전달하면 부모 내부에 물건을 렌더링 할 수 있습니다 (예 :renderChild
할 수 있습니다. 그러면 부모는 렌더링 방법 중에 사용할 수 있습니다.
이것은 OP가 요청한 것과는 다소 다르지만 일부 사람들은 재사용 가능한 특성을 만들고 싶었고 자식 구성 요소가 그렇게하는 좋은 방법이라고 생각했기 때문에 여기에서 끝날 수 있습니다.
답변
이런 식으로 쉽게 달성 할 수 있습니다
단계
- 부모 클래스의 상태에서 부울 변수를 만듭니다. 함수를 호출하려고 할 때 이것을 업데이트하십시오.
- prop 변수를 작성하고 부울 변수를 지정하십시오.
-
자식 구성 요소에서 props를 사용하여 해당 변수에 액세스하고 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> ); } }