โ ๏ธ ์ ๋ฆฌํ ๋ด์ฉ์ ์คํ๋ ์๋ชป๋ ์ ๋ณด๊ฐ ์์ ์ ์์ต๋๋ค. ๋๊ธ๋ก ์๋ ค์ฃผ์๋ฉด ๊ฐ์ฌํ๊ฒ ์ต๋๋ค.
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;
logProps
HOC๋ ๋ชจ๋ ย 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๋ฅผ ๊ตฌ์ฑํ ๋ ๋ ํธ๋ฆฌํ๊ฒ ๊ตฌํํ ์ ์์ ๊ฒ ๊ฐ๋ค.