
โ ๏ธ ์ ๋ฆฌํ ๋ด์ฉ์ ์คํ๋ ์๋ชป๋ ์ ๋ณด๊ฐ ์์ ์ ์์ต๋๋ค. ๋๊ธ๋ก ์๋ ค์ฃผ์๋ฉด ๊ฐ์ฌํ๊ฒ ์ต๋๋ค.
ref ์ ๋ฌ์ ์ปดํฌ๋ํธ๋ฅผ ํตํด ์์ ์ค ํ๋์ ref๋ฅผ ์๋์ผ๋ก ์ ๋ฌํ๋ ๊ธฐ๋ฒ์ด๋ค. ์ผ๋ฐ์ ์ผ๋ก ์ ํ๋ฆฌ์ผ์ด์
๋๋ถ๋ถ์ ์ปดํฌ๋ํธ์ ํ์ํ์ง๋ ์๋ค. ๊ทธ๋ ์ง๋ง, ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์ปดํฌ๋ํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๊ฐ์ ์ด๋ค ์ปดํฌ๋ํธ์์๋ ์ ์ฉํ ์ ์๋ค.
function FancyButton(props) {
return (
<button className="FancyButton">
{props.children}
</button>
);
}
FancyButton ๋ฅผ ์ฌ์ฉํ๋ ๋ค๋ฅธ ์ปดํฌ๋ํธ๋ค์ย ์ผ๋ฐ์ ์ผ๋กย ๋ด๋ถย buttonย DOM ์์์ ๋ํ ref๋ฅผ ์ป์ ํ์๊ฐ ์๋ค. ์ด๋ ์ปดํฌ๋ํธ๋ค์ด ์๋ก์ DOM ๊ตฌ์กฐ์ ์ง๋์น๊ฒ ์์กดํ์ง ์๊ธฐ ๋๋ฌธ์ ๊ด์ฐฎ๋ค.
์ด๋ฐ ์บก์ํ๋ย FeedStory๋ย Commentย ๊ฐ์ ์ ํ๋ฆฌ์ผ์ด์
๋ ๋ฒจ์ ์ปดํฌ๋ํธ์์๋ ๋ฐ๋์งํ์ง๋ง,ย FancyButton์ด๋ย MyTextInput๊ณผ ๊ฐ์ ์ฌ์ฌ์ฉ์ฑ์ด ๋์ ๋ง๋จ ์์(Leaf์์)์์๋ ๋ถํธํ ์๋ ์๋ค. ์ด๋ฐ ์ปดํฌ๋ํธ๋ค์ ์ผ๋ฐ์ ์ธ DOM, button, input๊ณผ ์ ์ฌํ ๋ฐฉ๋ฒ์ผ๋ก ์ ํ๋ฆฌ์ผ์ด์
์ ์ฒด์ ๊ฑธ์ณ ์ฌ์ฉ๋๋ ๊ฒฝํฅ์ด ์๋ค.
React ๊ธฐ์ ์ฉ์ด ๋ชจ์ - React
์ฌ๊ธฐ์ FeedStory๋ Comment ๋ ๋ณต์กํ UI(App, FeedStory, Comment)๋ฅผ ๋งํ๋ค.
Ref ์ ๋ฌํ๊ธฐ๋ ์ผ๋ถ ์ปดํฌ๋ํธ๊ฐ ์์ ํ ref๋ฅผ ๋ฐ์ ์กฐ๊ธ ๋ ์๋๋ก ์ ๋ฌ ํ ์ ์๋ ์ตํธ์ธ ๊ธฐ๋ฅ์ด๋ค.
const FancyButton = React.forwardRef((props, ref) => (
// 3. React๋ ์ด ref๋ฅผ forwardRef ๋ด๋ถ์ (props, ref) => ... ํจ์์ ๋ ๋ฒ์งธ ์ธ์๋ก ์ ๋ฌํฉ๋๋ค.
// 4. ์ด ref๋ฅผ JSX ์์ฑ์ผ๋ก ์ง์ ํด์ <button ref={ref}>์ผ๋ก ์ ๋ฌํฉ๋๋ค.
// 5. ref๊ฐ ์ฒจ๋ถ๋๋ฉด ref.current๋ <button> DOM ๋
ธ๋๋ฅผ ๊ฐ๋ฆฌํค๊ฒ ๋ฉ๋๋ค.
<button ref={ref} className="FancyButton">
{props.children}
</button>));
// ์ด์ DOM ๋ฒํผ์ผ๋ก ref๋ฅผ ์์ ๋ฐ์ ์ ์์ต๋๋ค.
const ref = React.createRef();
// 1. React.createRef๋ฅผ ํธ์ถํด์ React ref๋ฅผ ์์ฑํ๊ณ ref ๋ณ์์ ํ ๋นํ๋ค.
<FancyButton ref={ref}>Click me!</FancyButton>;
// 2. ref๋ฅผ JSX ์์ฑ์ผ๋ก ์ง์ ํด์ <FancyButton ref={ref}>๋ก ์ ๋ฌํฉ๋๋ค.
์์์ FancyButton์ React.forwardRef๋ฅผ ์ฌ์ฉํ์ฌ ์ ๋ฌ๋ ref๋ฅผ ์ป๊ณ ๊ทธ๊ฒ์ ๋ ๋๋ง๋๋ DOM ๋ฒํผ์ผ๋ก ์ ๋ฌํ๋ค. ์ด๋ ๊ฒ FancyButton์ ์ฌ์ฉํ๋ ์ปดํฌ๋ํธ๋ค์ button DOM ๋
ธ๋์ ๋ํ ์ฐธ์กฐ๋ฅผ ๊ฐ์ ธ์ฌ ์ ์๋ค.
์ปดํฌ๋ํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ย forwardRef๋ฅผ ์ฌ์ฉํ๊ธฐ ์์ํ ๋ ์ด๊ฒ์ ๋ณ๊ฒฝ์ฌํญ์ผ๋ก ๊ฐ์ฃผํ๊ณ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์๋ก์ด ์ค์ ๋ฒ์ ์ ๋ฆด๋ฆฌ์ฆ ํด์ผ ํ๋ค. ์ด๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ฃผ๋ชฉํ ๋งํ๊ฒ ๋ค๋ฅธ ๋์์ ํ ๊ฐ๋ฅ์ฑ์ด ๋๊ณ ์ด์ ๋์์ ์์กดํ๋ ์ฑ์ด๋ ๋ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ด ์์๋ ๊ฐ๋ฅ์ฑ์ด ํฌ๊ธฐ ๋๋ฌธ์ด๋ค.
function logProps(WrappedComponent) {
class LogProps extends React.Component {
componentDidUpdate(prevProps) {
console.log('old props:', prevProps);
console.log('new props:', this.props);
}
render() {
return <WrappedComponent {...this.props} />;
}
}
return LogProps;
logPropsHOC๋ ๋ชจ๋ ย props๋ฅผ ๋ํํ๋ ์ปดํฌ๋ํธ๋ก ์ ๋ฌํ๋ฏ๋ก ๋ ๋๋ง ๋ ๊ฒฐ๊ณผ๊ฐ ๋์ผํ๊ฒ ๋๋ค.
์๋ฅผ ๋ค์ด, ์ด HOC๋ฅผ ์ฌ์ฉํด์ FancyButton ์ปดํฌ๋ํธ๋ก ์ ๋ฌํ๋ ๋ชจ๋ props๋ฅผ ๊ธฐ๋ก ํ ์ ์๋ค.
class FancyButton extends React.Component {
focus() {
// ...
}
// ...
}
// FancyButton์ ๋ด๋ณด๋ด๋ ๋์ LogProps๋ฅผ ๋ด๋ณด๋
๋๋ค.
// ๊ทธ๋๋ FancyButton์ ๋ ๋๋งํฉ๋๋ค.
export default logProps(FancyButton);
ref๋ prop์ด ์๋๊ธฐ ๋๋ฌธ์ refs๋ ์ ๋ฌ๋์ง ์๋๋ค.ย key์ ๋ง์ฐฌ๊ฐ์ง๋กย ref๋ React์์ ๋ค๋ฅด๊ฒ ์ฒ๋ฆฌํ๋ค. HOC์ ref๋ฅผ ์ถ๊ฐํ๋ฉด ref๋ ๋ํ ๋ ์ปดํฌ๋ํธ๊ฐ ์๋๋ผ ๊ฐ์ฅ ๋ฐ๊นฅ์ชฝ ์ปจํ
์ด๋ ์ปดํฌ๋ํธ๋ฅผ ์ฐธ์กฐํ๋ค.
์ฆ, FancyButtonย ์ปดํฌ๋ํธ๋ฅผ ์ํ refs๊ฐ ์ค์ ๋ก๋ย LogPropsย ์ปดํฌ๋ํธ์ ์ฒจ๋ถ๋๋ค๋ ๊ฒ์ ์๋ฏธํ๋ค.
import FancyButton from './FancyButton';
const ref = React.createRef();
// ๊ฐ์ ธ์จ FancyButton ์ปดํฌ๋ํธ๋ LogProps HOC์ด๋ค..
// ๋ ๋๋ง๋ ๊ฒฐ๊ณผ๊ฐ ๋์ผํ๋ค๊ณ ํ๋๋ผ๋, ref๋ ๋ด๋ถ FancyButton ์ปดํฌ๋ํธ ๋์ LogProps๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
// ์ด๊ฒ์ ์ฐ๋ฆฌ๊ฐ ์๋ฅผ ๋ค์ด ref.current.focus()๋ฅผ ํธ์ถํ ์ ์๋ค๋ ๊ฒ์ ํ๋ค..
<FancyButton
label="Click Me"
handleClick={handleClick}
ref={ref}
/>;
React.forwardRefย API๋ฅผ ์ฌ์ฉํ์ฌ ๋ด๋ถย FancyButtonย ์ปดํฌ๋ํธ์ ๋ํ refs๋ฅผ ๋ช
์์ ์ผ๋ก ์ ๋ฌํ ์ ์๋ค.
function logProps(Component) {
class LogProps extends React.Component {
componentDidUpdate(prevProps) {
console.log('old props:', prevProps);
console.log('new props:', this.props);
}
render() {
const {forwardedRef, ...rest} = this.props;
// ์ฌ์ฉ์ ์ ์ prop "forwardedRef"๋ฅผ ref๋ก ํ ๋นํ๋ค.
return <Component ref={forwardedRef} {...rest} />;
}
}
// React.forwardRef์์ ์ ๊ณตํ๋ ๋ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ "ref"์ ์ฃผ์ํด์ผํ๋ค.
// ๊ฐ๋ น "forwardedRef"๊ฐ์ ์ผ๋ฐ prop์ผ๋ก LogProps์ ์ ๋ฌํ ์ ์๋ค.
// ๊ทธ ๋ค์ Component์ ์ฐ๊ฒฐํ ์ ์๋ค.
return React.forwardRef((props, ref) => {
return <LogProps {...props} forwardedRef={ref} />;
});
}
React DevTools๋ ์ด ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ref ์ ๋ฌ ์ปดํฌ๋ํธ์ ๋ํด์ ๋ฌด์์ ํ์ํ ๊ฒ์ธ์ง ์ ์ํ๋ค. ๋ ๋๋ง ํจ์๋ฅผ ์ง์ ํ๋ฉด DevTools์ ํด๋น ์ด๋ฆ๋ ํฌํจ๋๋ค.
const WrappedComponent = React.forwardRef(
function myFunction(props, ref) {
return <LogProps {...props} forwardedRef={ref} />;
}
);
React.forwardRef๋ฅผ ์ฌ์ฉํด์ ref๋ฅผ ์ป์ ์ ์๊ณ HOC์ ์ด ๋ถ๋ถ์ ์ ํ์ฉํ๋ฉด ์ปดํฌ๋ํธ ๋จ์๋ก UI๋ฅผ ๊ตฌ์ฑํ ๋ ๋ ํธ๋ฆฌํ๊ฒ ๊ตฌํํ ์ ์์ ๊ฒ ๊ฐ๋ค.