storybook 코드를 작성하던 중,
stories
파일과styled
컴포넌트 간에 prop들을 인자로 주고 받는 개념이 헷갈려서 확실하게 재정립 해보고자 구조분해할당에 대한 개념을 다시 알아보게 되었다.
구조를 분해하고 할당하는 것으로, ES6가 등장하면서 함께 구현된 방식이다.
구조분해를 통해 배열이나 객체에서 요소나 프로퍼티(key, value)를 분해하고, 분해된 것을 새로운 변수에 담을 수 있게 한다.
코드의 가독성을 높이고 간략화를 할 때 유용하게 사용된다.
//배열 구조 분해
const points = [20, 30, 40];
const [x, y, z] = points;
console.log(x, y, z); // 20 30 40
//객체 구조 분해
// ES5
const car = {
type: 'Toyota',
color: 'Silver',
model: 2007
};
const type = car.type;
const color = car.color;
const model = car.model;
console.log(type, color, model); // Toyota Silver 2007
// ES6
const {type, color, model} = car;
console.log(type, color, model); // // Toyota Silver 2007
App.js
: 부모 컴포넌트
Greet.js
: 자식 컴포넌트
// App.js (부모)
import React from 'react';
import Greet from './Greet'
class App extends React.Component {
render() {
return (
<div>
<Greet name="Diana" heroName="Wonder Woman" />
// Greet 컴포넌트에 name, heroName 인자 전달
</div>
)
}
}
export default App
// Greet.js (자식)
import React from 'react'
const Greet = props => { // 'props' 로 인자 전체 받아오기
return (
<div>
<h1>
Hello {props.name} a.k.a {props.heroName}
</h1>
</div>
)
}
export default Greet
부모 컴포넌트에서 자식 컴포넌트로 인자(props)들을 넘기는 방식.
const Greet = ({ name, heroName }) => { // 인자 안에서 분해
return (
<div>
<h1>
Hello {name} a.k.a {heroName}
</h1>
</div>
)
}
const Greet = props => {
const { name, heroName } = props; // 본문 안에서 분해
return (
<div>
<h1>
Hello {name} a.k.a {heroName}
</h1>
</div>
)
}
render
안에서 분해
// App.js
import React from 'react';
import Welcome from './Welcome'
class App extends React.Component {
render() {
return (
<div>
<Welcome name="Bruce" heroName="Batman" />
// Greet 컴포넌트에 name, heroName 인자 전달
</div>
)
}
}
export default App
// Welcome.js
class Welcome extends Component {
render() {
const { name, heroName } = this.props // props
const { state1, state2 } = this.state // state
return (
<h1>
Welcome {name} a.k.a {heroName}
</h1>
)
}
}
스토리(storybook)는 하나의 컴포넌트(styledRadio)에 대한 다양한 상태와 프로터피 설정을 보여주는 것이다.
Storybook 과 React를 사용할 때에는 이런 관계를 갖게 된다.
- Storybook 내
stories
- 스토리 파일이 부모- React
jsx
- 컴포넌트 파일이 자식
→ 스토리가 컴포넌트에게 prop(인자)를 전달하는 방식이 될 것.
// automateStoriesFromProps 함수 (utils 폴더 내 따로 관리)
export function automateStoriesFromProps(component) {
const Playground = (args) => React.createElement(component, args); //InitialTemplate
const stories = {};
if (component.__docgenInfo.props) {
const argsNames = Object.keys(component.__docgenInfo.props);
argsNames.forEach((argName) => {
stories[argName] = Playground.bind({});
stories[argName].argTypes = disableUnusedArgs(argsNames, argName);
});
}
stories['Playground'] = Playground;
return stories;
}
// Stories.js
import { automateStoriesFromProps } from '../utils/automateStorybook';
import { StyledRadio } from '../../src/components/styled-radio/medistream.jsx';
const { Playground, value, Val, Width: WidthHeight } = automateStoriesFromProps(StyledRadio);
automateStoriesFromProps
라는 함수에 인자로 StyledRadio
라는 컴포넌트를 전달받고 있다.automateStoriesFromProps
함수를 살펴보면, component
인자로 StyledRadio
를 받아와서 해당 컴포넌트의 프로퍼티들을 스토리로 만들어주는 역할을 한다. (component == StyledRadio)docgenInfo
와 forEach
함수를 활용하여 컴포넌트 내 프롭들을 관리하고 있다.→ automateStoriesFromProps
함수로부터 반환된 객체를 구조분해할당을 사용하여 각각의 변수들에 할당하고 있으며, 그 변수명들은 { Playground, value, Val, Width: WidthHeight }
인 것이다.
→ 이 변수들은 각각의 스토리를 나타내며, StyledRadio
컴포넌트의 다양한 프로퍼티 값을 보여준다.
// styledRadio.jsx
export const StyledRadio = (props) => {
const { Name, Val, Disabled, Width, Height, value, modelValue } = props;
return (
...
)
}
styledRadio
컴포넌트에서 부모로부터 props를 인자로 받아와 사용.요약 정리
Stories.js
파일에서는automateStoriesFromProps
함수를 사용하여StyledRadio
컴포넌트의 다양한 프로퍼티 상태를 보여주는 스토리들을 생성한다.
Playground
함수를 통해 각 스토리에서StyledRadio
컴포넌트에 프로퍼티 값을 설정하고 렌더링한다.
StyledRadio
컴포넌트는props
를 인자로 받아온다.→
Stories.js
에서Playground
함수를 호출할 때,args
객체에 프로퍼티 값을 설정하면 이 값들이StyledRadio
컴포넌트의props
로 전달된다.
const Playground = (args) => React.createElement(component, args);
→ 리액트의
createElement
함수를 사용하여component
변수에 할당된 컴포넌트(여기서는StyledRadio
)를 렌더링하고, 그 때args
객체를 컴포넌트의props
로 전달하는 것.이렇게 전달된 프로퍼티 값들은
StyledRadio
컴포넌트 내부에서 구조분해할당을 통해 추출되고 사용된다.
💡 간단히 말하면, 스토리에서 설정한 프로퍼티 값들이 args
객체에 담겨서 StyledRadio
컴포넌트의 props
로 전달되고, StyledRadio
컴포넌트 내에서 해당 프로퍼티 값을 인자로 받아 사용하게 된다는 것이다.
🔆 TIL
구조분해할당에 대해서는 익히 들고 알고 있었지만, 여러개의 함수로 이루어진 스토리 파일 코드 때문에 어디서 어디로 인자로 전달하는 건지 정확히 파악하기가 어려웠다. 하지만 이번 개념 정립을 통해createElement
라는 리액트 함수를 통해 인자를 전달하고 있다는 것을 알 수 있었다.