TIL - Storybook & React : 구조 분해 할당

신혜린·2023년 8월 14일
0

TIL

목록 보기
8/19
post-thumbnail

storybook 코드를 작성하던 중, stories 파일과 styled 컴포넌트 간에 prop들을 인자로 주고 받는 개념이 헷갈려서 확실하게 재정립 해보고자 구조분해할당에 대한 개념을 다시 알아보게 되었다.


🍎 구조분해할당?

구조를 분해하고 할당하는 것으로, ES6가 등장하면서 함께 구현된 방식이다.

구조분해를 통해 배열이나 객체에서 요소나 프로퍼티(key, value)를 분해하고, 분해된 것을 새로운 변수에 담을 수 있게 한다.

코드의 가독성을 높이고 간략화를 할 때 유용하게 사용된다.

ES6 구조분해 정의

//배열 구조 분해
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)들을 넘기는 방식.

🍏 함수 컴포넌트에서의 구조분해할당

1. 함수 인자 안에서 분해

const Greet = ({ name, heroName }) => { // 인자 안에서 분해
	return (
		<div>
			<h1>
				Hello {name} a.k.a {heroName}
			</h1>
		</div>
	)
}

2. 함수 본문 안에서 분해

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

Props & State

// 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)
    • docgenInfoforEach 함수를 활용하여 컴포넌트 내 프롭들을 관리하고 있다.

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를 인자로 받아와 사용.



요약 정리

  1. Stories.js 파일에서는 automateStoriesFromProps 함수를 사용하여 StyledRadio 컴포넌트의 다양한 프로퍼티 상태를 보여주는 스토리들을 생성한다.

  2. Playground 함수를 통해 각 스토리에서 StyledRadio 컴포넌트에 프로퍼티 값을 설정하고 렌더링한다.

  3. 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 라는 리액트 함수를 통해 인자를 전달하고 있다는 것을 알 수 있었다.

profile
개 발자국 🐾

0개의 댓글