부모로부터 자식 메서드 호출


474

두 가지 구성 요소가 있습니다.

  1. 부모 구성 요소
  2. 하위 구성 요소

부모님으로부터 자녀의 방법을 호출하려고했지만이 방법을 시도했지만 결과를 얻을 수 없었습니다.

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도 배우고 있으므로 부모가 자식 메소드를 호출 해야하는 경우에 대해 알고 싶습니다. 설명해 주시겠습니까?
Akshay Raut

화살표 기능을 사용 하여이 방법을 아는 사람이 있습니까? stackoverflow.com/questions/60015693/…
토마스 세가 토

@AkshayRaut IMO는 유용한 사용 사례 : 재설정 및 제출 기능이있는 범용 양식으로, 나중에 양식 값을 리턴합니다.
Julian K

답변:


702

먼저, 이것이 일반적으로 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>


23
피곤했지만 "_this2.refs.child.getAlert는 함수가 아닙니다"라는 오류로 끝납니다.
N8FURY

22
connect원래 인스턴스를 감싸는 고차 컴포넌트를 반환 하기 때문 입니다. getWrappedInstance()원래 구성 요소를 가져 오려면 먼저 연결된 구성 요소 를 호출해야합니다 . 그런 다음 인스턴스 메소드를 호출 할 수 있습니다.
rossipedia

16
이것은 실제로 좋은 패턴이 아닙니다. 말할 것도없이 문자열 심판은 눈살을 찌푸리게합니다. 소품을 자식 구성 요소에 전달 한 다음 부모에서 버튼 클릭으로 부모의 상태를 변경하고 상태 항목을 자식으로 전달하여 자식을 트리거하고 자식 componentWillReceiveProps으로 트리거하는 것이 좋습니다.
ffxsam

7
아니요, 일반적 으로 가장 좋은 패턴은 아니며 필요할 때 탈출구에 가깝기 때문에 긴급 상황에서만 사용해야합니다. 또한이 답변은 문자열 참조가 여전히 주변에있을 때 작성되었으며 요즘에는 "올바른"방법이 아닌 것이 맞습니다.
rossipedia

35
모범 사례가 자식 구성 요소의 메소드를 호출하는 것만 큼 간단한 작업을 수행하는 논리의 미로를 만드는 것이라면 모범 사례에 동의하지 않습니다.
aaaaaa

149

여기서 다른 패턴을 사용할 수 있습니다.

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자식이 마운트 될 때 부모의 방법 을 설정하는 것입니다. 이런 식으로 부모의 버튼을 클릭하면 clickChildchild 's를 호출합니다 getAlert.

이것은 자녀가 포장되어 해킹이 connect()필요하지 않은 경우에도 작동합니다 getWrappedInstance().

onClick={this.clickChild}부모가 렌더링 될 때 자식이 마운트 this.clickChild되지 않았으므로 아직 할당되지 않았 으므로 부모에서 사용할 수 없습니다 . onClick={() => this.clickChild()}버튼을 클릭하면 this.clickChild이미 할당되어 있어야 하기 때문에 사용하는 것이 좋습니다.


5
내가받을 _this2.clickChild is not a function이유는 무엇입니까?
tatsu

1
신경 끄시이 나를 위해 일한 : github.com/kriasoft/react-starter-kit/issues/...
tatsu

5
둘 다 작동하지 않았습니다. 이 답변 만 작동했습니다 : github.com/kriasoft/react-starter-kit/issues/…
tatsu

2
이것은 흥미로운 기술입니다. 그것은 매우 깨끗하고 규칙을 어기는 것 같지 않습니다. 그러나 바인드를 추가하면 귀하의 답변이 더 완전하고 기대에 부응한다고 생각합니다. 나는 관련 Github 이슈 에 게시 한 답변을 너무 좋아했다 .
joeytwiddle

7
이것은 acepted 대답해야한다
예수님 고메즈

27

https://facebook.github.io/react/tips/expose-component-functions.html 자세한 답변은 여기를 참조하십시오 React 하위 구성 요소에 대한 메소드 호출

"이유"구성 요소의 참조를 살펴보면 캡슐화가 깨지고 사용 된 모든 위치를 신중하게 검사하지 않고 해당 구성 요소를 리팩터링 할 수 없습니다. 이 때문에 ref는 상태와 매우 유사하게 구성 요소에 대한 비공개로 처리하는 것이 좋습니다.

일반적으로 데이터는 소품을 통해 트리로 전달되어야합니다. 이에 대한 몇 가지 예외가 있습니다 (예 : .focus () 호출 또는 상태를 실제로 "변경"하지 않는 일회성 애니메이션 트리거). "set"이라는 메서드를 노출 할 때마다 소품은 일반적으로 더 나은 선택입니다. 내부 입력 구성 요소가 크기와 모양에 대해 걱정하여 조상이 처리하지 않도록하십시오.


5
다음은이 답변의 소스는 다음과 같습니다 discuss.reactjs.org/t/... . 다른 사람들을 인용하는 데 아무런 문제가 없지만 적어도 참고로 언급하십시오.
Jodo

1
이것이 소품보다 캡슐화를 어떻게 정확히 깨뜨 립니까?
Timmmm

15

useEffect를 사용한 대체 방법 :

부모의:

const [refresh, doRefresh] = useState(0);
<Button onClick={()=>doRefresh(refresh+1)} />
<Children refresh={refresh} />

어린이:

useEffect(() => {
    refresh(); //children function of interest
  }, [props.refresh]);

2
더 많은 투표를해야합니다
알리 알 아민

추신. 입력 필드를 재설정하기 위해 양식을 다시 렌더링하려는 경우 useEffect를 포함 할 필요조차없이 소품을 구성 요소 변경으로 보내도록 할 수 있습니다.
Matt Fletcher

8

다른 방법으로 심판을 사용할 수 있습니다.

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>
        );
    }
}

소스 코드 는 다음과 같습니다 .
희망이 당신을 도울 것입니다!


1
문자열 참조는 더 이상 사용되지 않습니다. reactjs.org/docs/refs-and-the-dom.html#legacy-api-string-refs
Cory McAboy

4

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가 요청한 것과는 다소 다르지만 일부 사람들은 재사용 가능한 특성을 만들고 싶었고 자식 구성 요소가 그렇게하는 좋은 방법이라고 생각했기 때문에 여기에서 끝날 수 있습니다.


재사용 가능한 특성을 생성하기위한 편리한 패턴 목록이 여기 있습니다 : reactjs.org/blog/2016/07/13/…
joeytwiddle

N 개의 스톱워치와 하나의 버튼으로 모두 다시 시작하면 어떻게됩니까? 렌더링 소품은 여기서 어떻게 편리합니까?
vsync 2016 년

@vsync이 방법이 작업에 도움이 될지 잘 모르겠습니다. 그러나 brickingup의 대답 이 도움이 될 수 있습니다. 그것들이 설정 this.clickChild = click되었지만 다중 스톱워치는 여러 기능을 통과하므로 모든 기능을 저장해야합니다.this.watchRestartFuncs[watchId] = restartWatch
joeytwiddle

1

이런 식으로 쉽게 달성 할 수 있습니다

단계

  1. 부모 클래스의 상태에서 부울 변수를 만듭니다. 함수를 호출하려고 할 때 이것을 업데이트하십시오.
  2. prop 변수를 작성하고 부울 변수를 지정하십시오.
  3. 자식 구성 요소에서 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>
        );
       }
    }

이것을 샌드 박스로 만들고 싶을 수도 있습니다. 부모 상태가 true로 설정되어 있기 때문에 자식 메서드가 계속 실행되므로 무한 루프로 끝나는 것처럼 보입니다.
Isaac Pak

@IsaacPak 그래, 내가 당신의 요구 사항에 따라 상태를 업데이트해야한다는 의견을 남겼습니다. 그런 다음 무한 루프로 실행되지 않습니다.
Kusal Kithmal

1

나는 useEffect이 모든 일을하는 두통을 극복하기 위해 후크를 사용 하고 있으므로 이제 다음과 같이 변수를 자식에게 전달합니다.

<ParentComponent>
 <ChildComponent arbitrary={value} />
</ParentComponent>
useEffect(() => callTheFunctionToBeCalled(value) , [value]);

1

여기에 제시된 솔루션에 만족하지 않았습니다. 실제로 기본 props 객체 이외의 일부 React 기능에 의존하지 않고 순수 Javascript를 사용하여 수행 할 수있는 매우 간단한 솔루션이 있으며, 어느 방향 (부모-> 자식, 자식-> 부모)으로 통신하는 이점을 제공합니다. 부모 구성 요소에서 자식 구성 요소로 개체를 전달해야합니다. 이 개체는 "양방향 참조"또는 biRef라고합니다. 기본적으로 개체에는 부모가 노출하려는 부모의 메서드에 대한 참조가 포함됩니다. 자식 구성 요소는 부모가 호출 할 수있는 개체에 메서드를 연결합니다. 이 같은:

// Parent component.
function MyParentComponent(props) {

   function someParentFunction() {
      // The child component can call this function.
   }

   function onButtonClick() {
       // Call the function inside the child component.
       biRef.someChildFunction();
   }

   // Add all the functions here that the child can call.
   var biRef = {
      someParentFunction: someParentFunction
   }

   return <div>
       <MyChildComponent biRef={biRef} />
       <Button onClick={onButtonClick} />
   </div>;
}


// Child component
function MyChildComponent(props) {

   function someChildFunction() {
      // The parent component can call this function.
   }


   function onButtonClick() {
      // Call the parent function.
      props.biRef.someParentFunction();
   }

   // Add all the child functions to props.biRef that you want the parent
   // to be able to call.
   props.biRef.someChildFunction = someChildFunction;

   return <div>
       <Button onClick={onButtonClick} />
   </div>;
}

이 솔루션의 다른 장점은 단일 속성 만 사용하여 부모에서 자식으로 전달하는 동안 부모와 자식에 더 많은 기능을 추가 할 수 있다는 것입니다.

위 코드를 개선하면 부모 함수와 자식 함수를 biRef 개체에 직접 추가하는 것이 아니라 하위 멤버에 추가하는 것입니다. 부모 함수는 "parent"라는 멤버에 추가되어야하고 자식 함수는 "child"라는 멤버에 추가되어야합니다.

// Parent component.
function MyParentComponent(props) {

   function someParentFunction() {
      // The child component can call this function.
   }

   function onButtonClick() {
       // Call the function inside the child component.
       biRef.child.someChildFunction();
   }

   // Add all the functions here that the child can call.
   var biRef = {
      parent: {
          someParentFunction: someParentFunction
      }
   }

   return <div>
       <MyChildComponent biRef={biRef} />
       <Button onClick={onButtonClick} />
   </div>;
}


// Child component
function MyChildComponent(props) {

   function someChildFunction() {
      // The parent component can call this function.
   }


   function onButtonClick() {
      // Call the parent function.
      props.biRef.parent.someParentFunction();
   }

   // Add all the child functions to props.biRef that you want the parent
   // to be able to call.
   props.biRef {
       child: {
            someChildFunction: someChildFunction
       }
   }

   return <div>
       <Button onClick={onButtonClick} />
   </div>;
}

부모 함수와 자식 함수를 biRef 개체의 개별 멤버에 배치하면 둘 사이를 명확하게 분리 할 수 ​​있으며 부모 또는 자식에 속하는 함수를 쉽게 확인할 수 있습니다. 또한 동일한 기능이 둘 다에 나타나는 경우 하위 구성 요소가 실수로 상위 기능을 겹쳐 쓰는 것을 방지합니다.

마지막으로 부모 구성 요소는 var를 사용하여 biRef 개체를 만드는 반면 자식 구성 요소는 props 개체를 통해 액세스합니다. 부모에서 biRef 객체를 정의하지 않고 자체 props 매개 변수 (UI 요소의 계층 구조에 해당)를 통해 부모로부터 액세스하려는 유혹이있을 수 있습니다. 자식이 부모에게 호출하는 함수가 실제로 조부모에게 속할 수있을 때 부모에게 속한 함수라고 생각할 수 있기 때문에 위험합니다. 당신이 알고있는 한 이것에 아무런 문제가 없습니다. 부모 / 자식 관계 이외의 일부 계층 구조를 지원할 이유가없는 경우 부모 구성 요소에서 biRef를 만드는 것이 가장 좋습니다.



0

메서드를 호출하는 가장 기본적인 방법은 자식 구성 요소에 요청을 설정하는 것입니다. 그런 다음 자식이 요청을 처리하자마자 콜백 메소드를 호출하여 요청을 재설정합니다.

재설정 메커니즘은 동일한 요청을 서로 여러 번 보낼 수 있어야합니다.

부모 컴포넌트에서

부모의 render 메소드에서 :

const { request } = this.state;
return (<Child request={request} onRequestHandled={()->resetRequest()}/>);

부모는 두 방향으로 자녀와 의사 소통하기 위해 두 가지 방법이 필요합니다.

sendRequest() {
  const request = { param: "value" };
  this.setState({ request });
}

resetRequest() {
  const request = null;
  this.setState({ request });
}

자식 컴포넌트에서

자식은 내부 상태를 업데이트하여 소품의 요청을 복사합니다.

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;
}

그런 다음 마지막으로 요청을 처리하고 재설정을 부모에게 보냅니다.

componentDidMount() {
  const { request } = this.state;
  // todo handle request.

  const { onRequestHandled } = this.props;
  if (onRequestHandled != null) onRequestHandled();
}

0

부모에서 자식 함수를 트리거하는 또 다른 방법은 componentDidUpdate자식 구성 요소 의 함수를 사용하는 것입니다 . 소품 triggerChildFunc을 Parent에서 Child로 전달합니다 null. 버튼을 클릭하면 값이 함수로 바뀌고 자식은 변경되어 componentDidUpdate자체 내부 함수를 호출합니다.

prop triggerChildFunc이 함수로 바뀌기 때문에 부모에게 콜백을받습니다. Parent가 함수가 언제 호출되는지 알 필요가 없다면 triggerChildFunc예를 들어 값 이에서 null로 변경 될 수 있습니다 true.

const { Component } = React;
const { render } = ReactDOM;

class Parent extends Component {
  state = {
    triggerFunc: null
  }

  render() {
    return (
      <div>
        <Child triggerChildFunc={this.state.triggerFunc} />
        <button onClick={() => {
          this.setState({ triggerFunc: () => alert('Callback in parent')})
        }}>Click
        </button>
      </div>
    );
  }
}

class Child extends Component {
  componentDidUpdate(prevProps) {
    if (this.props.triggerChildFunc !== prevProps.triggerChildFunc) {
      this.onParentTrigger();
    }
  }

  onParentTrigger() {
    alert('parent triggered me');

    // Let's call the passed variable from parent if it's a function
    if (this.props.triggerChildFunc && {}.toString.call(this.props.triggerChildFunc) === '[object Function]') {
      this.props.triggerChildFunc();
    }
  }

  render() {
    return (
      <h1>Hello</h1>
    );
  }
}


render(
  <Parent />,
  document.getElementById('app')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id='app'></div>

코드 펜 : https://codepen.io/calsal/pen/NWPxbJv?editors=1010


0

여기 내 데모 : https://stackblitz.com/edit/react-dgz1ee?file=styles.css

useEffect자식 구성 요소의 메서드를 호출하는 데 사용 하고 있습니다. 나는 시도 Proxy and Setter_Getter했지만 useEffect부모로부터 자식 메서드를 호출하는 가장 편리한 방법 인 것 같습니다. Proxy and Setter_Getter그것을 사용하려면 먼저 렌더링 된 요소가 ref.current return => <div/>'특이성을 통해 objectLike의 요소이기 때문에 먼저 극복해야 할 미묘한 것 같습니다 . 에 관하여useEffect ,이 접근법을 활용하여 자녀와 함께하고 싶은 일에 따라 부모의 상태를 설정할 수도 있습니다.

내가 제공 한 데모 링크에서 내 초안이있는 ReactJS 코드 전체를 찾을 수 있으므로 솔루션의 워크 플로우를 이해할 수 있습니다.

여기에서는 관련 코드만으로 ReactJS의 스 니펫을 제공합니다. :

import React, {
  Component,
  createRef,
  forwardRef,
  useState,
  useEffect
} from "react"; 

{...}

// Child component
// I am defining here a forwardRef's element to get the Child's methods from the parent
// through the ref's element.
let Child = forwardRef((props, ref) => {
  // I am fetching the parent's method here
  // that allows me to connect the parent and the child's components
  let { validateChildren } = props;
  // I am initializing the state of the children
  // good if we can even leverage on the functional children's state
  let initialState = {
    one: "hello world",
    two: () => {
      console.log("I am accessing child method from parent :].");
      return "child method achieve";
    }
  };
  // useState initialization
  const [componentState, setComponentState] = useState(initialState);
  // useEffect will allow me to communicate with the parent
  // through a lifecycle data flow
  useEffect(() => {
    ref.current = { componentState };
    validateChildren(ref.current.componentState.two);
  });

{...}

});

{...}

// Parent component
class App extends Component {
  // initialize the ref inside the constructor element
  constructor(props) {
    super(props);
    this.childRef = createRef();
  }

  // I am implementing a parent's method
  // in child useEffect's method
  validateChildren = childrenMethod => {
    // access children method from parent
    childrenMethod();
    // or signaling children is ready
    console.log("children active");
  };

{...}
render(){
       return (
          {
            // I am referencing the children
            // also I am implementing the parent logic connector's function
            // in the child, here => this.validateChildren's function
          }
          <Child ref={this.childRef} validateChildren={this.validateChildren} />
        </div>
       )
}

0

우리는 우리가 호출하는 사용자 정의 후크에 만족합니다 useCounterKey. 단지 counterKey 또는 0부터 카운트되는 키를 설정합니다. 반환하는 함수는 키를 재설정합니다 (예 : 증분). (이것은 React에서 가장 관용적 인 방법 이라고 생각합니다 에서 구성 요소를 재설정하는 . 키를 만지면됩니다.)

그러나이 후크는 클라이언트에 일회성 메시지를 보내서 무언가를 수행하려는 모든 상황에서도 작동합니다. 예를 들어 우리는 특정 부모 이벤트에 대한 자식의 컨트롤에 초점을 맞추기 위해 사용합니다. 키가 업데이트 될 때마다 자동 초점됩니다. (더 많은 소품이 필요한 경우 키를 재설정하기 전에 설정할 수 있으므로 이벤트가 발생할 때 사용할 수 있습니다.)

이 방법은 일반적인 이벤트 핸들러만큼 간단하지는 않지만 약간의 학습 곡선을 가지고 있지만, 우리가 찾은 React에서 이것을 처리하는 가장 관용적 인 방법 인 것 같습니다 (키가 이미 이런 식으로 작동하기 때문에). Def는이 방법에 대한 피드백을 공개하지만 잘 작동하고 있습니다!

// Main helper hook:
export function useCounterKey() {
  const [key, setKey] = useState(0);
  return [key, () => setKey(prev => prev + 1)] as const;
}

샘플 사용법 :

// Sample 1 - normal React, just reset a control by changing Key on demand
function Sample1() {
  const [inputLineCounterKey, resetInputLine] = useCounterKey();

  return <>
    <InputLine key={inputLineCounterKey} />
    <button onClick={() => resetInputLine()} />
  <>;
}

// Second sample - anytime the counterKey is incremented, child calls focus() on the input
function Sample2() {
  const [amountFocusCounterKey, focusAmountInput] = useCounterKey();

  // ... call focusAmountInput in some hook or event handler as needed

  return <WorkoutAmountInput focusCounterKey={amountFocusCounterKey} />
}

function WorkoutAmountInput(props) {
  useEffect(() => {
    if (counterKey > 0) {
      // Don't focus initially
      focusAmount();
    }
  }, [counterKey]);

  // ...
}

( CounterKey 개념에 대해서는 Kent Dodds에게 감사드립니다 .)


-1

여기 버그가 있습니까? forwardRef, useRef, useImperativeHandle을 사용하여 rossipedia의 솔루션과 일치합니다.

온라인에서 Ref 클래스는 React Class 컴포넌트에서만 생성 될 수 있다는 잘못된 정보가 있지만 위에서 언급 한 후크를 사용하면 실제로 Function Components를 사용할 수 있습니다. 참고, 구성 요소를 내보낼 때 파일을 RoRoute ()와 함께 사용하지 않도록 변경 한 후에 만 ​​후크가 작동했습니다. 즉에서 변경

export default withRouter(TableConfig);

대신에

export default TableConfig;

가늠자에 withRouter ()는 어쨌든 그러한 구성 요소에 필요하지 않지만 일반적으로 구성 요소를 손상시키지 않습니다. 내 유스 케이스는 구성 값을보고 편집 할 수있는 테이블을 생성하는 구성 요소를 만든 것입니다. 부모 양식의 재설정 버튼을 누를 때 마다이 자식 구성 요소에 상태 값을 재설정하도록 지시하고 싶었습니다. 자식 구성 요소 TableConfig를 포함하는 파일에서 withRouter ()를 제거 할 때까지 UseRef ()가 ref 또는 ref.current (널을 가져 오는 경우)를 올바르게 얻지 못합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.