programing

리액트 후크 : 하위 컴포넌트에서 상위 컴포넌트로 데이터를 전송합니다.

elseif 2023. 3. 15. 19:23

리액트 후크 : 하위 컴포넌트에서 상위 컴포넌트로 데이터를 전송합니다.

자녀 컴포넌트의 데이터를 부모에게 전달할 수 있는 가장 쉬운 솔루션을 찾고 있습니다.

Context, pass trop properties, update 소품 중 어느 것이 가장 좋은 솔루션인지 모르겠습니다.

여러 줄을 선택할 수 있는 테이블이 있는 Child Component를 포함하는 Page Component를 사용하여 관리 인터페이스를 구축하고 있습니다.ChildComponent에서 선택한 라인 수를 부모 PageComponent로 전송하려고 합니다.

뭐 그런 거:

페이지 컴포넌트:

<div className="App">
  <EnhancedTable />         
  <h2>count 0</h2>
  (count should be updated from child)
</div>

Child Component:

 const EnhancedTable = () => {
     const [count, setCount] = useState(0);
     return (
       <button onClick={() => setCount(count + 1)}>
          Click me {count}
       </button>
     )
  };

아주 간단한 일이라 확신해요. 그런 일에 레덕스를 사용하고 싶지 않아요.

이러한 상황에서 일반적인 기술은 상태를 사용해야 하는 모든 구성요소의 첫 번째 공통 조상(즉, 상태를 사용해야 하는 구성 요소)까지 상태를 상승시키는 것입니다.PageComponent이 경우), 상태 및 상태 확인 기능을 소품으로 하위 구성요소에 전달합니다.

const { useState } = React;

function PageComponent() {
  const [count, setCount] = useState(0);
  const increment = () => {
    setCount(count + 1)
  }

  return (
    <div className="App">
      <ChildComponent onClick={increment} count={count} />         
      <h2>count {count}</h2>
      (count should be updated from child)
    </div>
  );
}

const ChildComponent = ({ onClick, count }) => {
  return (
    <button onClick={onClick}>
       Click me {count}
    </button>
  )
};

ReactDOM.render(<PageComponent />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>

부모 컴포넌트에 메서드를 작성하여 자녀 컴포넌트에 전달하고 자녀 상태가 변경될 때마다 소품에서 호출하여 자녀 컴포넌트에 상태를 유지할 수 있습니다.

    const EnhancedTable = ({ parentCallback }) => {
        const [count, setCount] = useState(0);
        
        return (
            <button onClick={() => {
                const newValue = count + 1;
                setCount(newValue);
                parentCallback(newValue);
            }}>
                 Click me {count}
            </button>
        )
    };

    class PageComponent extends React.Component { 
        callback = (count) => {
            // do something with value in parent component, like save to state
        }

        render() {
            return (
                <div className="App">
                    <EnhancedTable parentCallback={this.callback} />         
                    <h2>count 0</h2>
                    (count should be updated from child)
                </div>
            )
        }
    }

매우 심플하게 하기 위해 상태 설정기를 실제로 자녀와 공유할 수 있으며, 이제 자녀는 부모의 상태를 설정할 수 있습니다.

예:다음과 같은 4개의 컴포넌트가 있다고 가정합니다.

function App() {
  return (
    <div className="App">
      <GrandParent />
    </div>
  );
}

const GrandParent = () => {
  const [name, setName] = useState("i'm Grand Parent");
  return (
    <>
      <div>{name}</div>
      <Parent setName={setName} />
    </>
  );
};

const Parent = params => {
  return (
    <>
      <button onClick={() => params.setName("i'm from Parent")}>
        from Parent
      </button>
      <Child setName={params.setName} />
    </>
  );
};

const Child = params => {
  return (
    <>
      <button onClick={() => params.setName("i'm from Child")}>
        from Child
      </button>
    </>
  );
};

따라서 할아버지 컴포넌트는 실제 상태를 가지며 setter 메서드(setName)를 부모 및 자녀에게 공유함으로써 할아버지 컴포넌트의 상태를 변경할 수 있는 접근권을 얻을 수 있습니다.

작업 코드는 아래 샌드박스, https://codesandbox.io/embed/async-fire-kl197에서 찾을 수 있습니다.

Have Parent Class Component and Child 함수 컴포넌트가 있는 경우 이렇게 하면 하위 컴포넌트 useStates hooks value:--에 액세스할 수 있습니다.

class parent extends Component() {
 
  constructor(props){
    super(props)
    this.ChildComponentRef = React.createRef()   
  }
  
  render(){
    console.log(' check child stateValue: ', 
    this.ChildComponentRef.current.info);
    return (<> <ChildComponent ref={this.ChildComponentRef} /> </>)
 }
}

다음을 사용하여 작성하는 하위 구성 요소

React.forwardRef((props, ref) => (</>)

.그리고.

use Imperative Handle(ref, create Handle, [deps])

상위 구성 요소에 노출되는 인스턴스 값을 사용자 정의하려면

const childComponent = React.forwardRef((props, ref) => {
   const [info, setInfo] = useState("")

   useEffect(() => {
      axios.get("someUrl").then((data)=>setInfo(data))
   })

  useImperativeHandle(ref, () => {
      return {
          info: info
      }
  })
  return (<> <h2> Child Component <h2> </>)
 })

나는 이것을 활자 대본으로 해야 했다.오브젝트 지향적인 측면에서는 부모로부터 상속받은 후 이 콜백메서드를 인터페이스의 필드로 추가하려면 dev가 필요하며 이 프로포트의 유형은 Function이 됩니다.이거 신기하다!

다음은 상태를 부모에게 직접 전달할 수 있는 또 다른 예입니다.

React-Select 라이브러리에서 구성 요소 예를 수정했습니다. 이 라이브러리는 Creatable입니다.컴포넌트를 선택합니다.이 컴포넌트는 원래 클래스 베이스 컴포넌트로 개발되어 기능 컴포넌트로 전환하여 상태 조작 알고리즘을 변경하였습니다.

import React, {KeyboardEventHandler} from 'react';
import CreatableSelect from 'react-select/creatable';
import { ActionMeta, OnChangeValue } from 'react-select';

const MultiSelectTextInput = (props) => {
    const components = {
        DropdownIndicator: null,
    };

    interface Option {
        readonly label: string;
        readonly value: string;
    }

    const createOption = (label: string) => ({
        label,
        value: label,
    });

    const handleChange = (value: OnChangeValue<Option, true>, actionMeta: ActionMeta<Option>) => {
        console.group('Value Changed');
        console.log(value);
        console.log(`action: ${actionMeta.action}`);
        console.groupEnd();
        props.setValue(value);
    };

    const handleInputChange = (inputValue: string) => {
        props.setInputValue(inputValue);
    };

    const handleKeyDown: KeyboardEventHandler<HTMLDivElement> = (event) => {
        if (!props.inputValue) return;

        switch (event.key) {
            case 'Enter':
            case 'Tab':
                console.group('Value Added');
                console.log(props.value);
                console.groupEnd();
                props.setInputValue('');
                props.setValue([...props.value, createOption(props.inputValue)])
                event.preventDefault();
        }
    };

    return (
        <CreatableSelect
            id={props.id}
            instanceId={props.id}
            className="w-100"
            components={components}
            inputValue={props.inputValue}
            isClearable
            isMulti
            menuIsOpen={false}
            onChange={handleChange}
            onInputChange={handleInputChange}
            onKeyDown={handleKeyDown}
            placeholder="Type something and press enter..."
            value={props.value}
        />
    );
};

export default MultiSelectTextInput;

다음 js프로젝트 페이지에서 이렇게 부릅니다.

import MultiSelectTextInput from "../components/Form/MultiSelect/MultiSelectTextInput";

const NcciLite = () => {
    const [value, setValue] = useState<any>([]);
    const [inputValue, setInputValue] = useState<any>('');

    return (
        <React.Fragment>
            ....
            <div className="d-inline-flex col-md-9">
                <MultiSelectTextInput
                    id="codes"
                    value={value}
                    setValue={setValue}
                    inputValue={inputValue}
                    setInputValue={setInputValue}
                />
            </div>
            ...
        </React.Fragment>
    );
};

표시된 것처럼 컴포넌트는 호출된 페이지의 (상위 페이지의) 상태를 수정합니다.

비슷한 문제를 해결해야 했고, 동일한 파일에서 객체를 사용하여 다른 함수 간의 상태를 참조하는 다른 방법을 찾았습니다.

import React, { useState } from "react";

let myState = {};

const GrandParent = () => {
  const [name, setName] = useState("i'm Grand Parent");
  myState.name=name;
  myState.setName=setName;
  return (
    <>
      <div>{name}</div>
      <Parent />
    </>
  );
};
export default GrandParent;

const Parent = () => {
  return (
    <>
      <button onClick={() => myState.setName("i'm from Parent")}>
        from Parent
      </button>
      <Child />
    </>
  );
};

const Child = () => {
  return (
    <>
      <button onClick={() => myState.setName("i'm from Child")}>
        from Child
      </button>
    </>
  );
};

언급URL : https://stackoverflow.com/questions/55726886/react-hook-send-data-from-child-to-parent-component