๐Ÿงถ React์˜ ์•”์‹œ์  CLSX

9159 ๋‹จ์–ด vuereactclsxjsx
clsx ์—์„œ classnames ๋˜๋Š” React์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ์ตœ๊ทผ Tailwind CSS๊ณผ ๊ฐ™์€ ์œ ํ‹ธ๋ฆฌํ‹ฐ ์šฐ์„  CSS ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ ์ถ”์„ธ๊ฐ€ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ด ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ๋Š” ๋งŽ์€ ํด๋ž˜์Šค๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•˜๋ฉฐ ๋•Œ๋กœ๋Š” ์กฐ๊ฑด๋ฌธ๋„ ํ•จ๊ป˜ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Vue๊ณผ ๊ฐ™์€ ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ ์™”๋‹ค๋ฉด ์ด Class Binding ๊ธฐ๋Šฅ์ด ์ฆ‰์‹œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๋ธ”๋กœ๊ทธ ๊ฒŒ์‹œ๋ฌผ์—์„œ๋Š” React ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํŒจ์น˜ํ•˜์—ฌ ํ•„์š”ํ•  ๋•Œ๋งˆ๋‹ค ๊ฐ€์ ธ์˜ค๊ธฐclsx๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  React์—์„œ๋„ ๊ธฐ๋Šฅ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

โ˜ข๏ธ This is just for learning purposes. Use at your own risk



์ƒˆ๋กœ์šด React ์•ฑ ๋งŒ๋“ค๊ธฐ




yarn create react-app implicit-clsx
cd implicit-clsx


clsx ์„ค์น˜




yarn add clsx


๋ฐ˜์‘ ์ œ๊ฑฐ




yarn remove react


raw-react ์ด๋ฆ„์œผ๋กœ ๋ฐ˜์‘ ์„ค์น˜(์ถ”๊ฐ€ ์ •๋ณด)




yarn add raw-react@npm:react


์›์‹œ ๋ฐ˜์‘์—์„œ ๋‚ด๋ณด๋‚ผ ์ž์ฒด React ๋งŒ๋“ค๊ธฐ



๋‚ด ๋ฐ˜์‘/index.js

module.exports = require('raw-react')


my-react/jsx-runtime.js(์ •๋ณด)

module.exports = require('raw-react/jsx-runtime')


my-react/jsx-dev-runtime.js(์ •๋ณด)

module.exports = require('raw-react/jsx-dev-runtime')


๋ฐ˜์‘ ํŒจํ‚ค์ง€๋กœ my-react ์„ค์น˜(์ž์„ธํ•œ ์ •๋ณด)




yarn add react@file:my-react


JSX ๋Ÿฐํƒ€์ž„ ํŒจ์น˜



์ด์ œ JSX Runtime์„ ํŒจ์น˜ํ•˜์—ฌ className๋ฅผ ํ™•์ธํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ํž˜๋“  ์ผ์ด ์˜จ๋‹ค ๐Ÿ˜€



my-react/jsx-dev-runtime.js

module.exports = require('raw-react/jsx-dev-runtime')

const clsx = require('clsx').default
const jsxDEV = module.exports.jsxDEV

module.exports.jsxDEV = function() {
    if (typeof arguments[0] === 'string' && arguments[1].className) {
        arguments[1].className = clsx(arguments[1].className)
    }

    return jsxDEV.apply(undefined, arguments)
}


์ด์ œ ๋‚ด๊ฐ€ ์—ฌ๊ธฐ์— ์“ด ํšก์„ค์ˆ˜์„ค์„ ์„ค๋ช… ํ•  ์‹œ๊ฐ„์ž…๋‹ˆ๋‹ค ๐Ÿคฃ ๋ช‡ ๊ฐ€์ง€๋งŒ ์„ค๋ช…ํ•˜๊ณ  ๋‹ค๋ฅธ ๋ชจ๋“  ๊ฒƒ์€ ๋ถ„๋ช…ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค

  • arguments arguments๋Š” ํ•ด๋‹น ํ•จ์ˆ˜์— ์ „๋‹ฌ๋œ ์ธ์ˆ˜์˜ ๊ฐ’์„ ํฌํ•จํ•˜๋Š” ํ•จ์ˆ˜ ๋‚ด์—์„œ ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฐ์—ด๊ณผ ๊ฐ™์€ ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค.

  • apply apply() ๋ฉ”์„œ๋“œ๋Š” ์ฃผ์–ด์ง„ this ๊ฐ’๊ณผ ๋ฐฐ์—ด(๋˜๋Š” ๋ฐฐ์—ด๊ณผ ์œ ์‚ฌํ•œ ๊ฐ์ฒด)๋กœ ์ œ๊ณต๋œ ์ธ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.

  • ๊ธฐ๋Šฅ ์„œ๋ช…jsxDEV์€ type, props, key์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ arguments[0]๋Š” type์ด๊ณ  arguments[1]๋Š” props์ž…๋‹ˆ๋‹ค.
    react-dom์—์„œ ํ˜ธ์ŠคํŠธ ์š”์†Œ๋Š” ๋ฌธ์ž์—ด๋งŒ ๋  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์œ ํ˜•์ด ๋ฌธ์ž์—ด์ธ์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์ผ๋ถ€ ํ•จ์ˆ˜ ๋˜๋Š” ํด๋ž˜์Šค ๊ตฌ์„ฑ ์š”์†Œ์—์„œ ๋ณ€๊ฒฝclassName์„ ์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

    ๋‘ ๋ฒˆ์งธ๋กœ className ์†Œํ’ˆ์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ  clsx ํ˜ธ์ถœ๋กœ ํŒจ์น˜ํ•ฉ๋‹ˆ๋‹ค.

    ํ•จ์ˆ˜์˜ ๋งˆ์ง€๋ง‰ ์ค„์—์„œ ๋ชจ๋“  ๊ฒƒ์„ ๋„ค์ดํ‹ฐ๋ธŒ๋กœ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹คjsxDEV.

    To have this work also on build, you will need to apply this patch also to jsx and jsxs in my-react/jsx-runtime.js see repo link at the end



    ์—…๋ฐ์ดํŠธํ•˜๋ ค๋ฉด ๋ฐ˜์‘ ํŒจํ‚ค์ง€๋กœ my-react๋ฅผ ๋‹ค์‹œ ์„ค์น˜ํ•˜์„ธ์š”.




    yarn add react@file:my-react
    


    App.js๋ฅผ ๋ณ€๊ฒฝํ•˜์—ฌ ๋ณ€๊ฒฝ ์‚ฌํ•ญ ํ™•์ธ



    ์ค„์„ ๋ฌธ์ž์—ด๋กœ ๋‹จ์ผclassName๋กœ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.

    <div className="App">
    


    ์ผ๋ฐ˜์ ์œผ๋กœ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋Š” ๋Œ€์ƒclsx
    <div className={["App1", "App1", { "App2": true }]}>
    


    ์•ฑ์„ ์‹œ์ž‘ํ•˜๊ณ  ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ฒดํฌ์ธํ•˜์ž




    yarn start
    




    ์ž‘์—… ์˜ˆhttps://github.com/iamandrewluca/implicit-clsx

    TypeScript ๋ฒ„์ „์„ ๊ฐ€์ง€๊ณ  ๋†€์•˜์ง€๋งŒ ์œ ํ˜• ๋ถˆ์ผ์น˜๋กœ ์ธํ•ด ์ž‘๋™ํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ๋” ๋งŽ์€ ์กฐ์‚ฌ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

    ๊ทธ๋ฆฌ๊ณ  ๋๋‚ฌ์Šต๋‹ˆ๋‹ค! ๋‚ด ๋ธ”๋กœ๊ทธ ๊ฒŒ์‹œ๋ฌผ์„ ์ฝ์–ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!



    ํ‘œ์ง€ ์‚ฌ์ง„ ์ž‘์„ฑ์ž: Ash from Modern Afflatus on Unsplash

    ์ข‹์€ ์›นํŽ˜์ด์ง€ ์ฆ๊ฒจ์ฐพ๊ธฐ