React: ๊ฒฝ๊ณ : prop์ด 'null'์ธ ๊ฒฝ์šฐ PropTypes.object.isRequired

์— ๋งŒ๋“  2015๋…„ 02์›” 16์ผ  ยท  37์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: facebook/react

PropTypes ๊ฐ€ prop์˜ '์œ ํ˜•'์— ๋Œ€ํ•œ ๊ฒƒ์ด๋ฏ€๋กœ null ๋Š” ๋นˆ ๊ฐ์ฒด์ด์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” ์—ฌ์ „ํžˆ ๊ฐ์ฒด ์œ ํ˜•์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์—ฌ์ „ํžˆ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ฒฝ๊ณ ํ•ฉ๋‹ˆ๋‹ค.

 Warning: Required prop `profile` was not specified in `Element`. Check the render method of `OtherElement`.

๋‚˜๋Š” ์ด๊ฒƒ์ด ์ผ์–ด๋‚˜์„œ๋Š” ์•ˆ๋œ๋‹ค๊ณ  ์ƒ๊ฐํ•œ๋‹ค.

๋” ์ด์ƒ null ๊ฐ€ ์•„๋‹Œ ํ›„์— ๊ฒฝ๊ณ ๋ฅผ ์ค‘์ง€ํ•ฉ๋‹ˆ๋‹ค. undefined ๋•Œ๋งŒ ๊ฒฝ๊ณ ํ•ด์•ผ ํ•œ๋‹ค๊ณ  ํ™•์‹ ํ•ฉ๋‹ˆ๋‹ค.

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

๋‚ด๊ฐ€ ๋ณด๋Š” ์ผ๋ฐ˜์ ์ธ ์‚ฌ์šฉ ์‚ฌ๋ก€๋Š” ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ API ํ˜ธ์ถœ์ด ์™„๋ฃŒ๋˜๊ธฐ ์ „์— ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋ Œ๋”๋งํ•˜๋Š” React์ž…๋‹ˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ ๋ Œ๋”๋ง์€ ์˜ˆ๋ฅผ ๋“ค์–ด ํ•ญ๋ชฉ ๋ชฉ๋ก( items: null )์„ ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ API ํ˜ธ์ถœ์ด ์™„๋ฃŒ๋˜๊ณ  ์ด์ œ items ๊ฐ€ ๋ฐฐ์—ด๋กœ ์ฑ„์›Œ์ง‘๋‹ˆ๋‹ค.

๋ชจ๋“  37 ๋Œ“๊ธ€

null ๋Š” ๊ฐ’์ด ์—†๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•˜๋ฉฐ ๊ฐ์ฒด๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค(๋น„์–ด ์žˆ๊ฑฐ๋‚˜ ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ). null ์— ๋Œ€ํ•ด ๊ฒฝ๊ณ ํ•˜์ง€ ์•Š์œผ๋ ค๋ฉด ํ•„์ˆ˜ ํ•ญ๋ชฉ์œผ๋กœ ์ง€์ •ํ•˜์ง€ ์•Š์•„๋„ ๋™์ผํ•œ ํšจ๊ณผ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ํ‚ค์˜ ์กด์žฌ ์—ฌ๋ถ€๋ฅผ ํ…Œ์ŠคํŠธํ•˜๋Š” ๊ฒƒ์€ ๋‚ด๊ฐ€ ๊ถŒ์žฅํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹™๋‹ˆ๋‹ค.

๋‚˜๋Š” ๋™์˜ํ•œ๋‹ค. ์‚ฌ์šฉ์ž์—๊ฒŒ ๊ฐ’์„ ์ง€์ •ํ•˜๋„๋ก ๊ฐ•์ œํ•˜๊ณ  ์‹ถ์ง€๋งŒ null์„ ์œ ํšจํ•œ ๊ฐ’์œผ๋กœ ๊ธฐ๊บผ์ด ๋ฐ›์•„๋“ค์ด๋Š” ์‚ฌ์šฉ ์‚ฌ๋ก€๋Š” ๋งŽ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์‹ค์šฉ์ ์ธ ๋ชฉ์ ์„ ์œ„ํ•ด null์— ๋Œ€ํ•œ isRequired ๊ฒฝ๊ณ ๋Š” ํ•ฉ๋ฆฌ์ ์ด๊ณ  ์˜ˆ์ƒ๋˜๋Š” ๋™์ž‘์ž…๋‹ˆ๋‹ค.

๊ด€๋ จ: https://github.com/facebook/react/issues/2166
(์ด ๋ฌธ์ œ๋Š” ์—ฌ์ „ํžˆ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ์— ๋‘๋“œ๋Ÿฌ์ง€๊ฒŒ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค)

๋‚ด๊ฐ€ ๋ณด๋Š” ์ผ๋ฐ˜์ ์ธ ์‚ฌ์šฉ ์‚ฌ๋ก€๋Š” ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ API ํ˜ธ์ถœ์ด ์™„๋ฃŒ๋˜๊ธฐ ์ „์— ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋ Œ๋”๋งํ•˜๋Š” React์ž…๋‹ˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ ๋ Œ๋”๋ง์€ ์˜ˆ๋ฅผ ๋“ค์–ด ํ•ญ๋ชฉ ๋ชฉ๋ก( items: null )์„ ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ API ํ˜ธ์ถœ์ด ์™„๋ฃŒ๋˜๊ณ  ์ด์ œ items ๊ฐ€ ๋ฐฐ์—ด๋กœ ์ฑ„์›Œ์ง‘๋‹ˆ๋‹ค.

๋‚˜๋Š” PropTypes.oneOfType([null, PropTypes.object]).isRequired ์‹œ๋„ํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ null ๋˜๋Š” ๊ฐ์ฒด ์ค‘ ํ•˜๋‚˜๊ฐ€ ํ˜„์žฌ ๊ฐ€๋Šฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๊นŒ?

CHANGELOG ์— ๋”ฐ๋ฅด๋ฉด 15.4.0 ์ดํ›„๋กœ ๊ฐ€๋Šฅํ•˜๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.

์‚ฌ์‹ค, 15.4.0์—์„œ๋Š” ๋ฐ˜๋Œ€์ž…๋‹ˆ๋‹ค: Required PropTypes now fail with specific messages for null and undefined.

๋‚˜๋Š” ๋˜ํ•œ์ด ๋ฌธ์ œ์— ์ง๋ฉด ํ•ด ์žˆ์Šต๋‹ˆ๋‹ค.
@Noitidart ์˜ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ด ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
Failed prop type: The prop ๊ฐ’ is marked as required in , but its value is null .

์†์„ฑ์ด ํ•„์š”ํ•˜์ง€๋งŒ null ๊ฐ’๋„ ํ—ˆ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ •๋ง ์œ ์šฉํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์•˜์Šต๋‹ˆ๋‹ค.

null ์–ด๋–ป๊ฒŒ๋“  ํ—ˆ์šฉํ•œ ๊ฒƒ์— ๋Œ€ํ•ด +1์ž…๋‹ˆ๋‹ค.

๊ตฌ์„ฑ์ด JSON์„ ํ†ตํ•ด ๋กœ๋“œ๋˜๋Š” ์‚ฌ์šฉ ์‚ฌ๋ก€๊ฐ€ ์žˆ์œผ๋ฉฐ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ‘œ์‹œ๋˜์–ด์•ผ ํ•˜๋Š” ๋ฌธ์ž์—ด์„ ์ง€์ •ํ•˜๋Š” ์—ฌ๋Ÿฌ ๋ ˆ์ด๋ธ” ๊ตฌ์„ฑ ์˜ต์…˜์ด ์žˆ์Šต๋‹ˆ๋‹ค.

{
  "title": "my title"
}

๋”ฐ๋ผ์„œ ์ œ๋ชฉ์„ ํ‘œ์‹œํ•˜์ง€ ์•Š์•„์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ null ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•ด๋‹น ์‚ฌ๋ก€๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

{
  "title": null
}

(์ด๋Ÿฌํ•œ ์„ค์ •์ด ์ˆ˜์‹ญ ๊ฐœ ์žˆ์œผ๋ฏ€๋กœ ๋ณ‘๋ ฌ hasTitle: false ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์€ ๊ธˆ์ง€๋ฉ๋‹ˆ๋‹ค.)

JSON ์ฝ˜ํ…์ธ ์˜ ๊ฒฝ์šฐ null์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ์ •์˜๋˜์ง€ ์•Š์€ ๊ฒƒ( undefined )๊ณผ ์˜๋„์ ์œผ๋กœ ์ƒ๋žต๋œ ๊ฒƒ( null )์„ ๊ตฌ๋ณ„ํ•˜๋Š” ๋งค์šฐ ์œ ์šฉํ•œ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

null์„ ํ—ˆ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. propType์€ ํ•„์ˆ˜๊ฐ€ ์•„๋‹ˆ๋ฏ€๋กœ ํ•„์š”ํ•˜์ง€ ์•Š๋„๋ก ์„ค์ •ํ•˜์‹ญ์‹œ์˜ค.

@jquense ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค ๋งค์šฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค! ์ด SO ๋‹ต๋ณ€ ์ด ๊ฐ™์€ ๋‚ด์šฉ์„ ๋งํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด์ „ ์˜๊ฒฌ์„ ์‚ญ์ œํ–ˆ์Šต๋‹ˆ๋‹ค.

@jquense null AND undefined๋Š” ํ—ˆ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋‘˜ ์ค‘ ํ•˜๋‚˜๋Š” ํ—ˆ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ทธ๊ฒƒ์ด ๋ชจ๋“  ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค! Javascript๋Š” ์ด๋Ÿฌํ•œ 2๊ฐ€์ง€ ๋‹ค๋ฅธ ๊ตฌ์„ฑ์„ ์ œ๊ณตํ•œ ๋ฐ๋Š” ์ด์œ ๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ ๋ชจ๋“  ์‚ฌ๋žŒ์ด PropTypes์— ๋Œ€ํ•ด null === undefined ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋„๋ก ํ•˜๋Š” ๊ฒƒ์€ ์ธ์œ„์ ์ธ ์ œํ•œ์ž…๋‹ˆ๋‹ค.

PropType์ด null์„ ๋ช…์‹œ์ ์œผ๋กœ ํ—ˆ์šฉํ•˜๊ธฐ๋ฅผ ์›ํ•œ๋‹ค๊ณ  ํ•ด์„œ undefined๋„ ํ—ˆ์šฉํ•ด์•ผ ํ•œ๋‹ค๋Š” ์˜๋ฏธ๋Š” ์•„๋‹™๋‹ˆ๋‹ค. ๊ทธ๋“ค์€ ๋‘ ๊ฐ€์ง€ ๋ณ„๊ฐœ์˜ ๊ฒฝ์šฐ์ด๋ฉฐ ์–ธ์–ด๋Š” ์˜๋„์ ์œผ๋กœ ๊ทธ๋ ‡๊ฒŒ ์„ค๊ณ„ํ–ˆ์Šต๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์—์„œ ์ด ๊ฐ๋…์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ PR์ด ์žˆ์Šต๋‹ˆ๋‹ค: https://github.com/facebook/prop-types/pull/90

undefined ๋ฅผ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š” ์ด์œ ๋Š” ์˜คํƒ€๊ฐ€ ์žˆ์Œ์„ ์˜๋ฏธํ•˜๊ณ  null ํ—ˆ์šฉํ•œ๋‹ค๋Š” ๊ฒƒ์€ ํ˜ธ์ถœ์ž๊ฐ€ null ๋ช…์‹œ์ ์œผ๋กœ ์ „๋‹ฌํ–ˆ์Œ์„ ์˜๋ฏธํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ์ด ๋ฌธ์ œ์˜ ์š”์ ์ž…๋‹ˆ๋‹ค. ํ๋ฆ„์œผ๋กœ ์ „ํ™˜ํ•˜๋Š” ๊ฒƒ์ด ๊ถŒ์žฅ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ด ๋ฌธ์ œ๊ฐ€ ์ข…๋ฃŒ๋˜์—ˆ์Œ์„ ์ดํ•ดํ•ฉ๋‹ˆ๋‹ค.

@binki null ํ•˜์ง€๋งŒ undefined ๋Š” ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š” ํ•œ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์€ ๊ณ ์œ ํ•œ PropType ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๊ธฐ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์•„๋ž˜ ์˜ˆ์—์„œ๋Š” null ๋˜๋Š” string ๋งŒ ํ—ˆ์šฉ๋ฉ๋‹ˆ๋‹ค. PropTypes ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ typeof ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฌธ์ž์—ด์„ ํ™•์ธํ•˜๋ฏ€๋กœ ๋™์ผํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•œ ๊ฐ€์ง€ ์ด์ ์€ ์ด ํ•จ์ˆ˜๋ฅผ ๊ตฌ์„ฑ ์š”์†Œ ์™ธ๋ถ€๋กœ ์ด๋™ํ•˜๊ณ  ํ•„์š”์— ๋”ฐ๋ผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

static propTypes = {
  id: PropTypes.number.isRequired,
  email: function(props, propName, componentName) {
    const propValue = props[propName] // the actual value of `email` prop
    if (propValue === null) return
    if (typeof propValue === 'string') return
    return new Error(`${componentName} only accepts null or string`)
  }
}

๋‚˜๋Š” ์ด ์†”๋ฃจ์…˜์ด PropTypes ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์˜๋„์—์„œ ๋ฒ—์–ด๋‚œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค - ๋‚ด๊ฐ€ ์ด๊ฒƒ์„ ๋งํ•˜๋Š” ์ด์œ ๋Š” https://github.com/facebook/prop-types/blob/master/factoryWithTypeCheckers.js์— ์žˆ๋Š” PropTypes ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์•„๋ž˜ ์ฝ”๋“œ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์‹ค์ œ๋กœ ์œ ํšจ์„ฑ์„ ๊ฒ€์‚ฌํ•˜๊ธฐ ์ „์— ์†์„ฑ ๊ฐ’์ด null ์ด๋ฉด isRequired๋กœ ์„ค์ •๋œ ์†์„ฑ์ด ์ž๋™์œผ๋กœ ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๋Š” ๋น ๋ฅธ ๊ฒ€์‚ฌ๊ฐ€ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๋ง๋กœ ํ•˜๋ฉด ๊ทธ๋“ค์€ ํ•„์ˆ˜ ์†์„ฑ์ด null์ธ ๊ฒƒ์ด ์ž˜๋ชป๋œ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ ๋‚˜๋Š” ํ•„์ˆ˜ null์ด ์žˆ๋Š” ๊ฒƒ์ด ์œ ํšจํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

if (props[propName] == null) {
  if (isRequired) {
    if (props[propName] === null) {
      return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required ' + ('in `' + componentName + '`, but its value is `null`.'));
    }
    return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required in ' + ('`' + componentName + '`, but its value is `undefined`.'));
  }
  return null;
} else {
  return validate(props, propName, componentName, location, propFullName);
}

๋ช…์‹œ๋œ ์ด์œ ๋กœ @jharris4 ์— ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. null ๋Š” undefined ์™€ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ์ž๋ฆฌ ํ‘œ์‹œ์ž๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ํ‘œ์ค€์ž…๋‹ˆ๋‹ค.

Mozilla ๊ฐœ๋ฐœ์ž ๋„คํŠธ์›Œํฌ์—์„œ:

null ๊ฐ’์€ ๊ฐœ์ฒด ๊ฐ’์ด ์˜๋„์ ์œผ๋กœ ์—†์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

null์€ undefined์™€ ๊ฐ™์ด ์ „์—ญ ๊ฐœ์ฒด์˜ ์†์„ฑ์— ๋Œ€ํ•œ ์‹๋ณ„์ž๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ๋Œ€์‹  null์€ ์‹๋ณ„ ๋ถ€์กฑ์„ ๋‚˜ํƒ€๋‚ด๋ฉฐ ๋ณ€์ˆ˜๊ฐ€ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค์ง€ ์•Š์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. API์—์„œ null์€ ์ข…์ข… ๊ฐœ์ฒด๊ฐ€ ์˜ˆ์ƒ๋˜์ง€๋งŒ ๊ด€๋ จ ๊ฐœ์ฒด๊ฐ€ ์—†๋Š” ์œ„์น˜์—์„œ ๊ฒ€์ƒ‰๋ฉ๋‹ˆ๋‹ค.

null์€ ์ ์–ด๋„ PropTypes.oneOfType([null, PropTypes.string]).isRequired ํ†ตํ•ด ํ—ˆ์šฉ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

@jquense โ€” isRequired ์ œ๊ฑฐํ•˜๋ฉด ๊ธฐ๋ณธ๊ฐ’์„ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ null ๋ฅผ ์†Œํ’ˆ์˜ ๊ฐ’์œผ๋กœ ํ—ˆ์šฉํ•˜๋Š” ๊ฒƒ์„ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ์†๊ธฐ์˜ ๊ตฌ์„ฑ ์š”์†Œ _๋ฐ_์˜ ์ดˆ๊ธฐ ๊ฐ’์— ๋Œ€ํ•œ ๊ธฐ๋ณธ๊ฐ’์„ ์„ค์ •ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๊นŒ?

API ํ˜ธ์ถœ์„ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋™์•ˆ ์„ ํƒ๊ธฐ์— data || '' ( isRequired ๋นˆ ๋ฌธ์ž์—ด '' , ๋นˆ ๊ฐœ์ฒด {} ๋“ฑ)์ด ๋งŽ์ด ์žˆ์Šต๋‹ˆ๋‹ค. finish null ๋Š” ๊ตฌ์„ฑ ์š”์†Œ์— ๋ฐ์ดํ„ฐ๊ฐ€ ์˜ฌ ๊ฒƒ์ด๋ผ๊ณ  ์•Œ๋ ค์ฃผ๋Š” ์™„๋ฒฝํ•œ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ์ž ์‹œ๋งŒ ๊ธฐ๋‹ค๋ฆฌ์„ธ์š”! (ํ•˜์ง€๋งŒ ๋‚œ ๊ทธ๋Ÿด ์ˆ˜ ์—†์–ด...)
@puiu91 ์€ ์ง€๊ธˆ ์ข‹์€ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค... ์ฝ”๋“œ๋ฒ ์ด์Šค์—์„œ ์‚ฌ์šฉํ•  ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค... ์ด ๋ฌธ์ œ๊ฐ€ ๊ณง ๋‹ค์‹œ ์—ด๋ฆฌ์ง€ ์•Š์„ ๊ฒƒ ๊ฐ™๊ธฐ ๋•Œ๋ฌธ์— ํ•œ์ˆจ

๋‚˜๋Š” ๋˜ํ•œ @jharris4 ์™€ @Findiglay๊ฐ€ ์–ธ๊ธ‰ํ•œ ๊ฒƒ๊ณผ ๊ฐ™์€ ์ด์œ ๋กœ null ๋ฅผ ๊ฐ’์œผ๋กœ ๋ฐ›์•„๋“ค์ด๋Š” ํ‘œ์ค€ ๋ฐฉ๋ฒ•์ด ์žˆ์–ด์•ผ ํ•œ๋‹ค๋Š” ๋ฐ ๋™์˜ํ•˜์ง€๋งŒ, ์ด๊ฒƒ์€ ๋” ์ด์ƒ ๋…ผ์˜๋ฅผ ๊ณ„์†ํ•  ์žฅ์†Œ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋Š” ์ข…๋ฃŒ๋˜์—ˆ์„ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ facebook/prop-types ์— ์†ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ facebook/prop-types#90์—์„œ pull ์š”์ฒญ์„ ๋”ฐ๋ฅด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ถฉ๋Œ. ์˜ค๋Š˜๋‚ ์—๋„ ์—ฌ์ „ํžˆ ์‹คํ–‰ ์ค‘์ž…๋‹ˆ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ธฐ๋Šฅ์„ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ง€์›ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

myObj: PropType.object.isRequiredOrNull :)

๋‚˜๋Š” ์ด๊ฒƒ์— ๋Œ€ํ•œ ์šฐ์„  ์ˆœ์œ„๊ฐ€ ๋งค์šฐ ๋‚ฎ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ํ๋ฆ„์€ ๊ถŒ์žฅ๋˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. http://flow.org/

@Marujah ์Šค๋‹ˆํŽซ์ด ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ตฌ์„ฑ ์š”์†Œ์— null์„ ์ „๋‹ฌํ•˜๋ฉด ๊ฒฝ๊ณ ๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

Warning: Failed prop type: The prop 'theProp' is marked as required in 'TheComponent', but its value is null.

๋ฌธ์ œ๋Š” isRequired๊ฐ€ ๋จผ์ € ํ‰๊ฐ€๋˜๊ณ  null ๋˜๋Š” ์ •์˜๋˜์ง€ ์•Š์€ ๊ฐ’์„ ํ†ต๊ณผ์‹œํ‚ค์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ด€์‹ฌ์ด ์žˆ๋Š” ๊ฒฝ์šฐ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ prop-types์— ๋Œ€ํ•œ PR์ด ์œ„์— ๋งํฌ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

์•„ ์ •๋ง! ๋‹ค์‹œ ํ•œ ๋ฒˆ ๋‹น์‹ ์ด ์˜ณ๋‹ค

๊ฐ’ ๋˜๋Š” null์ด ๊ตฌ์ฒด์ ์œผ๋กœ ์ œ๊ณต๋˜์–ด์•ผ ํ•œ๋‹ค๋Š” ์š”๊ตฌ๋Š” PropTypes๋ฅผ ํ†ตํ•ด ์ ˆ๋Œ€์ ์œผ๋กœ ํ—ˆ์šฉ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ์€ ๋‚ด๊ฐ€ ๊ฒช๊ณ  ์žˆ๋Š” ์‚ฌ์šฉ ์‚ฌ๋ก€์ž…๋‹ˆ๋‹ค. ์„ ํƒ์ž์˜ 90%๊ฐ€ ํ•„์š”๋กœ ํ•˜๋Š” ๋ช‡ ๊ฐ€์ง€ ์ฝœ๋ฐฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ๋“ค์ด ํ•„์š”ํ•˜์ง€ ์•Š์€ ์†Œ์ˆ˜๋Š” ๋งค์šฐ ๊ตฌ์ฒด์ ์ธ ์‚ฌ์šฉ ์‚ฌ๋ก€์ž…๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์ธ ์ฝœ๋ฐฑ์„ ๋ชจ๋‘ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์„ ์ง€์†์ ์œผ๋กœ ์žŠ์–ด๋ฒ„๋ฆฌ๋Š” ์ƒˆ๋กœ์šด ๊ฐœ๋ฐœ์ž๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๊ตฌ์„ฑ ์š”์†Œ์˜ ๋ชจ๋“  ์‚ฌ์šฉ์ด ํŠน์ • ์ฝœ๋ฐฑ์„ ํฌํ•จํ•˜์ง€ ์•Š๋„๋ก ์˜์‹์ ์ธ ๊ฒฐ์ •์„ ๋‚ด๋ฆฌ๋„๋ก ๊ฐ•์ œํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ๋ช‡ ๊ฐ€์ง€ ์†Œํ’ˆ์„ ์žŠ์–ด๋ฒ„๋ฆฌ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ.

์˜ˆ, ํ๋ฆ„์„ ํ†ตํ•ด ๋ณด๋‹ค ๊ตฌ์ฒด์ ์ธ ๊ฒ€์‚ฌ๋ฅผ ํ•ดํ‚นํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์ด๋Š” props ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ๋‘ ๊ณณ์œผ๋กœ ๋ถ„ํ• ํ•˜๊ณ  propTypes ์ •์˜๋ฅผ ์‚ดํŽด๋ณด๋Š” ์‚ฌ๋žŒ์—๊ฒŒ๋Š” ๋‹ค์†Œ ์ง๊ด€์ ์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์— ๋‚ด ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜จ ์‹œ๊ฐ„๊ณผ ํ•จ๊ป˜ ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ๋Š” redux ์ €์žฅ์†Œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ค๋ฅ˜๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ๋“ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚ด ๊ตฌ์„ฑ ์š”์†Œ์—๋Š” '์˜ค๋ฅ˜' ์†Œํ’ˆ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค(๋”ฐ๋ผ์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ ์‚ฌ์šฉ์ž์—๊ฒŒ ์˜ค๋ฅ˜๋ฅผ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ์Œ). ๋ฐ์ดํ„ฐ๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ๋กœ๋“œ๋˜๋ฉด null์ด์ง€๋งŒ ์˜ค๋ฅ˜๊ฐ€ ์žˆ์œผ๋ฉด ์ฑ„์›Œ์ง‘๋‹ˆ๋‹ค.

๋กœ๋” ๊ตฌ์„ฑ ์š”์†Œ( PropTypes.node )๋ฅผ props ์ „๋‹ฌํ•˜๊ณ  ๋กœ๋”๋ฅผ ๋ Œ๋”๋งํ•˜์ง€ ์•Š์œผ๋ ค๋ฉด null ํ•ฉ๋‹ˆ๋‹ค.
Afaik, render ํ•จ์ˆ˜๋Š” ์•„๋ฌด ๊ฒƒ๋„ ๋ Œ๋”๋งํ•˜์ง€ ์•Š์„ ๋•Œ undefined ๋Œ€์‹  null ๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ null ๋ฅผ ๊ฐ’์œผ๋กœ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ด ์˜ฌ๋ฐ”๋ฅธ ๋ฐฉ๋ฒ•์œผ๋กœ ๋ณด์ž…๋‹ˆ๋‹ค.

๋‚ด๊ฐ€ InputNumber ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๊ตฌํ˜„ํ–ˆ๋‹ค (๋ž˜ํผ <input type="number"> ), ๋‚ด๊ฐ€ ๊ฐ€์ง„ ๊ทธ๋ž˜์„œ propTypes ๋‚ด ์†Œํ’ˆ์— ๋Œ€ํ•œ value - PropTypes.number.isRequired , ๊ทธ๋ฆฌ๊ณ  ๋‚ด ๊ตฌ์„ฑ ์š”์†Œ, I๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ํ•ญ์ƒ ์†์„ฑ์„ ์ „๋‹ฌํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์˜ค๋Š˜์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ฐ’์— ๋Œ€ํ•œ ๋งํฌ๋ฅผ nullable๋กœ ์ „๋‹ฌํ•ด์•ผ ํ•˜๋ฉฐ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ๊ฒฝ๊ณ ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ์ƒ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์œ ์ผํ•œ ๊ฒฐ์ •์€ propTypes ๋Œ€ํ•œ value ๋ฅผ PropTypes.oneOfType([PropTypes.number, PropTypes.string]) ํ•˜๊ณ  defaultProps ๋ฅผ null๋กœ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ input type=number๋Š” ์ˆซ์ž๋กœ๋งŒ ์ž‘๋™ํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์˜ฌ๋ฐ”๋ฅธ ๊ฒƒ์ด ์•„๋‹ˆ๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๋‚˜๋Š” PropTypes.oneOfType([null, PropTypes.object]).isRequired ์‹œ๋„ํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ null ๋˜๋Š” ๊ฐ์ฒด ์ค‘ ํ•˜๋‚˜๊ฐ€ ํ˜„์žฌ ๊ฐ€๋Šฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๊นŒ?

Warning: Invalid argument supplied to oneOfType. Expected an array of check functions, but received null at index 1. ํ•จ์ˆ˜๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

PropTypes.oneOfType([
  () => null,
  PropTypes.object
]).isRequired

๋ฐฉ๊ธˆ ์ด ๋ฒ„๊ทธ๊ฐ€ ๋ฐœ์ƒํ•˜์—ฌ ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ํŽธ์˜ ๊ธฐ๋Šฅ์„ ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

function nullable(subRequirement) {
  const check = (required, props, key, ...rest) => {
    if (props[key] === null) {
      return null;
    }
    const sub = required ? subRequirement.isRequired : subRequirement;
    return sub(props, key, ...rest);
  };
  const fn = check.bind(null, false);
  fn.isRequired = check.bind(null, true);
  return fn;
}

์šฉ๋ฒ•:

static propTypes = {
  someCallbackFunction: nullable(PropTypes.func).isRequired,
};

nullable ์—†์ด isRequired nullable ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค(๊ทธ๋Ÿฌ๋‚˜ ์˜คํžˆ๋ ค ๋ฌด์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค). isRequired ์™€ ํ˜ธํ™˜๋˜๋„๋ก ๋งŒ๋“  ์ด์œ ๋Š” react/require-default-props eslint ๊ทœ์น™๊ณผ ํ•จ๊ป˜ ์ž‘๋™ํ•˜๊ธฐ ์œ„ํ•จ์ž…๋‹ˆ๋‹ค.

๋‚ด ์‚ฌ์šฉ ์‚ฌ๋ก€๋Š” ์ฝœ๋ฐฑ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋‹จ์ผ ๊ตฌ์„ฑ ์š”์†Œ๋กœ ๋ž˜ํ•‘๋œ ๊ณตํ†ต API๋ฅผ ์ค€์ˆ˜ํ•˜๋Š” ์ผ๋ จ์˜ ๊ตฌ์„ฑ ์š”์†Œ์ž…๋‹ˆ๋‹ค. null ์ฝœ๋ฐฑ์€ '์ฝ๊ธฐ ์ „์šฉ'์„ ์˜๋ฏธํ•˜๋ฏ€๋กœ ๋ž˜ํผ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ๋•Œ๋•Œ๋กœ ์˜๋„์ ์œผ๋กœ null ํ•ฉ๋‹ˆ๋‹ค. ๋™์‹œ์— ์ƒˆ ์†์„ฑ์ด ์ถ”๊ฐ€๋  ๋•Œ ๋ˆ„๋ฝ๋˜์ง€ ์•Š๋„๋ก ๋ชจ๋“  ์†์„ฑ์„ ํ•˜์œ„ ๊ตฌ์„ฑ ์š”์†Œ์— ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ์ด API๋ฅผ ์ค€์ˆ˜ํ•˜๋Š” ๋ชจ๋“  ๊ตฌ์„ฑ ์š”์†Œ์— ๋Œ€ํ•ด defaultProps null์„ ์ œ๊ณตํ•˜๊ณ  ์‹ถ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋“ค์ด ์•Œ๊ณ  ์žˆ๋Š” ํ•œ ํ˜ธ์ถœ์ž๋Š” ๊ฐ’์„ ์ง€์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋‚˜๋Š” ์ „์— ์ž‘์„ฑํ•œ ๋„์šฐ๋ฏธ๋ฅผ ๊ฐ€์ ธ ์™€์„œ ์ •ํ™•์„ฑ์„ ์ฆ๋ช…ํ•˜๊ธฐ ์œ„ํ•ด ๋งŽ์€ ํ…Œ์ŠคํŠธ์™€ ํ•จ๊ป˜ ํŒจํ‚ค์ง€์— ๋„ฃ์—ˆ์Šต๋‹ˆ๋‹ค.

npm install --save git+https://github.com/davidje13/prop-types-nullable.git#semver:^1.0.0

์šฉ๋ฒ•:

import PropTypes from 'prop-types';
import nullable from 'prop-types-nullable';

[...]

static propTypes = {
  thing: nullable(PropTypes.string).isRequired,
};

์ƒˆ๋กœ์šด ์†”๋ฃจ์…˜: PropTypes.oneOfType([PropTypes.object]).isRequired

์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
์–ด๋–ป๊ฒŒ ๊ณ ์น˜๋Š” ์ง€.

./~/prop-types/prop-types.js์˜ ๊ฒฝ๊ณ  ์ค‘์š”ํ•œ ์ข…์†์„ฑ: 1:482-489 ์ด๊ฒƒ์€ ๋ฏธ๋ฆฌ ๋นŒ๋“œ๋œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๊ฐ€๋Šฅํ•˜์ง€๋งŒ ๊ถŒ์žฅ๋˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. ๋” ๋‚˜์€ ๊ฒฐ๊ณผ๋ฅผ ์–ป์œผ๋ ค๋ฉด ์›๋ณธ ์†Œ์Šค๋ฅผ ์š”๊ตฌํ•˜์‹ญ์‹œ์˜ค. @ ./~/prop-types/prop-types.js 1:482-489

๋‚˜๋Š” PropTypes.oneOfType([null, PropTypes.object]).isRequired ์‹œ๋„ํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ null ๋˜๋Š” ๊ฐ์ฒด ์ค‘ ํ•˜๋‚˜๊ฐ€ ํ˜„์žฌ ๊ฐ€๋Šฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๊นŒ?

Warning: Invalid argument supplied to oneOfType. Expected an array of check functions, but received null at index 1. ํ•จ์ˆ˜๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

PropTypes.oneOfType([
  () => null,
  PropTypes.object
]).isRequired

์‚ฌ์‹ค ๋งˆ์ง€๋ง‰์— 'isRequired'๋ผ๋Š” ์˜ค๋ฅ˜ ๋•Œ๋ฌธ์— ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ๋Š”๋ฐ, null์ธ ๋™์‹œ์— ํ•„์ˆ˜๋Š” ํ˜ธํ™˜๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค...
์ด๊ฒƒ์ด ๋‚˜๋ฅผ ์œ„ํ•ด ์ผํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

PropTypes.oneOfType([ 
    PropTypes.string.isRequired, 
    () => null 
])

@ gugol2 ๊ทธ๋ƒฅ ๋น„ํ™œ์„ฑํ™” ํƒ€์ž…์ด ์™„์ „ํžˆ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค ์ž‘์„ฑํ•œ ๊ฒƒ์„์ฃผ์˜ํ•˜์‹ญ์‹œ์˜ค (๋‹น์‹ ์ด ์ง€๊ธˆ ์†Œํ’ˆ์— ๋ฒˆํ˜ธ๋ฅผ ํ†ต๊ณผ, ๋˜๋Š” ์ˆ˜ undefined , ๋˜๋Š” ์•„๋ฌด๊ฒƒ๋„); ๊ท€ํ•˜๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ์€ ๋ฐ˜ํ™˜ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค null ๊ฒ€์ฆ์ด ์„ฑ๊ณตํ•˜๊ณ ์žˆ๋Š” ๊ฒฝ์šฐ ๋น„ null ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค.

ํ•ด๋‹น ๊ฒฝ๋กœ๋กœ ์ด๋™ํ•˜๋ ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒƒ์ด ๋” ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

PropTypes.oneOfType([
  PropTypes.string.isRequired,
  (props, key) => props[key] === null ? null : 'Not null'
])

๋ฌผ๋ก  ๋ณด๊ธฐ ํ‰ํ•œ ๋„์šฐ๋ฏธ ํ•จ์ˆ˜๋ฅผ ๋ฏธ๋ฆฌ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

const nullable = (props, key) => props[key] === null ? null : 'Not null'

// ...

PropTypes.oneOfType([PropTypes.string.isRequired, nullable])

PropTypes.oneOfType([PropTypes.string.isRequired]) ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋„ ๊ธฐ์ดํ•˜๊ฒŒ๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค(ํ•˜์ง€๋งŒ ์ •๋ง ์ถ”์ฒœํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค!). ์ด๊ฒƒ์€ ๋ฒ„๊ทธ์ฒ˜๋Ÿผ ๋Š๊ปด์ง€๋ฉฐ ๊ทธ๋Ÿฐ ์ฝ”๋“œ๊ฐ€ ์ดํ›„ ๋ฒ„์ „์—์„œ ์‚ด์•„๋‚จ์„ ๊ฒƒ์ด๋ผ๊ณ  ๊ธฐ๋Œ€ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ์ด์ „์— ์ œ์•ˆ๋œ ๋ฐฉ๋ฒ• ๊ณผ ์œ ์‚ฌํ•˜์ง€๋งŒ ๋™์ผํ•˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค.


๊ธฐ๋‹ค๋ฆด ์ˆ˜ ์žˆ๋‹ค๋ฉด ๋ฏฟ์„ ์ˆ˜ ์—†์„ ์ •๋„๋กœ ๋Š๋ฆฌ๊ฒŒ ์›€์ง์ด์ง€๋งŒ ๋ถ„๋ช…ํžˆ ์—ฌ์ „ํžˆ ๊ณ ๋ ค ์ค‘์ธ ๊ณต๊ฐœ PR ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  PR์ด ๋ณ‘ํ•ฉ๋  ๋•Œ๊นŒ์ง€ ๋‚ด๊ฐ€ ๋งŒ๋“  ํŒจํ‚ค์ง€ (๋˜๋Š” ๊ทธ ๋’ค์— ์žˆ๋Š” .isRequired ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ Linting ๊ทœ์น™๊ณผ ํ˜ธํ™˜๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

IMHO ์ด๊ฒƒ์€ ์˜ฌ๋ฐ”๋ฅธ ๋™์ž‘์ด์ง€๋งŒ ๋ฌธ์„œํ™”ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋‚ด๊ฐ€ ๋ณด๋Š” ์ผ๋ฐ˜์ ์ธ ์‚ฌ์šฉ ์‚ฌ๋ก€๋Š” ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ API ํ˜ธ์ถœ์ด ์™„๋ฃŒ๋˜๊ธฐ ์ „์— ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋ Œ๋”๋งํ•˜๋Š” React์ž…๋‹ˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ ๋ Œ๋”๋ง์€ ์˜ˆ๋ฅผ ๋“ค์–ด ํ•ญ๋ชฉ ๋ชฉ๋ก( items: null )์„ ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ API ํ˜ธ์ถœ์ด ์™„๋ฃŒ๋˜๊ณ  ์ด์ œ items ๊ฐ€ ๋ฐฐ์—ด๋กœ ์ฑ„์›Œ์ง‘๋‹ˆ๋‹ค.

์ด๊ฒƒ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? ์ด ์†Œํ’ˆ์ด ํ•„์š”ํ•˜์ง€๋งŒ API์—์„œ ๋‹ค์‹œ ๊ฐ€์ ธ์˜ค๊ธฐ ์ „์— null์ž…๋‹ˆ๋‹ค.

PropTypes.oneOfType([
  PropTypes.string.isRequired,
  (props, key) => props[key] === null ? null : 'Not null'
])

@ davidje13 ์ด ์ ‘๊ทผ ๋ฐฉ์‹์— ์•ฝ๊ฐ„์˜ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ ์šฉ ๋ฒ”์œ„ ํ…Œ์ŠคํŠธ์—๋Š” ์ ์šฉ๋˜์ง€ ์•Š๋Š” 1/4 ์ผ€์ด์Šค๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

null ๋˜๋Š” ๋ฌธ์ž์—ด์ด ํ•„์š”ํ•  ์ˆ˜ ์žˆ๋Š” ํ•˜๋‚˜์˜ prop 'name'๋งŒ ์žˆ๋Š” ๋กœ๊ทธ์ธ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

const Login = ({name}) => {
  return <div>{name}</div>
} 

๋”ฐ๋ผ์„œ ๊ทธ proptypes๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

Login.propTypes = {
  name: PropTypes.oneOfType([
    PropTypes.string.isRequired,
    (props, key) => (props[key] === null ? null : 'Not null'),
  ]),
};

์ด ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ํ…Œ์ŠคํŠธํ•  ๋•Œ null ๋˜๋Š” ํ•„์ˆ˜ ๋ฌธ์ž์—ด์˜ 2๊ฐ€์ง€ ์‹œ๋‚˜๋ฆฌ์˜ค๋งŒ ์žˆ์Šต๋‹ˆ๋‹ค.

render(<Login name={null} />
render(<Login name={'anyName'} />

๊ทธ๋Ÿฌ๋‚˜ ์ ์šฉ ๋ฒ”์œ„์— ๋”ฐ๋ฅด๋ฉด ๋‚ด ํ…Œ์ŠคํŠธ์—๋Š” 75%๋งŒ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.
์ด์— ๋Œ€ํ•œ ๊ณต์‹์ ์ธ ์ ‘๊ทผ์€ ์–ด๋–ป๊ฒŒ ๋˜๋Š”์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค.

๋ˆ„๋ฝ๋œ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค๊ฐ€ ์†Œํ’ˆ ๊ฒ€์‚ฌ์— ์‹คํŒจํ•œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๊นŒ? ์ฆ‰, ์ˆซ์ž๋‚˜ ์ •์˜๋˜์ง€ ์•Š์€ ๊ฒƒ์„ ์ „๋‹ฌํ•˜๋ฉด ์•ˆ ๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋ˆ„๋ฝ๋œ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค๊ฐ€ ์†Œํ’ˆ ๊ฒ€์‚ฌ์— ์‹คํŒจํ•œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๊นŒ? ์ฆ‰, ์ˆซ์ž๋‚˜ ์ •์˜๋˜์ง€ ์•Š์€ ๊ฒƒ์„ ์ „๋‹ฌํ•˜๋ฉด ์•ˆ ๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์•„๋‹ˆ, ๊ทธ๊ฒŒ ์•„๋‹ˆ์•ผ.

undefined๋ฅผ ์ „๋‹ฌํ•ด๋„ ์ ์šฉ ๋ฒ”์œ„๊ฐ€ ํ™•์žฅ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ์–ด์จŒ๋“  ์ˆซ์ž๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ํ—ˆ์šฉ๋˜๋Š” ๊ฐ’์ด ์•„๋‹™๋‹ˆ๋‹ค.

๋‚˜๋Š” ๊ทธ ์‚ฌ๊ฑด์„ ๋ฎ์„ ์ˆ˜ ์—†๋‹ค.

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰