React: λ°˜μ‘μ€ 쀑첩 된 μ»¨ν…μŠ€νŠΈλ₯Ό μ–΄λ–»κ²Œ ν•΄κ²°ν•©λ‹ˆκΉŒ?

에 λ§Œλ“  2019λ…„ 01μ›” 18일  Β·  38μ½”λ©˜νŠΈ  Β·  좜처: facebook/react

λ‚˜λŠ” λ§Žμ€ λ§₯락을 가지고 있고 λ‚˜λŠ” 이런 μ‹μœΌλ‘œ μ¨μ•Όλ§Œν•œλ‹€. μ§€κΈˆ λ‚΄ μž‘μ—…μ„ λ°©ν•΄ν•©λ‹ˆλ‹€. μ΄λŸ¬ν•œ λ””μžμΈμ€ 거의 μ‚¬μš©ν•  수 μ—†κ²Œ λ§Œλ“­λ‹ˆλ‹€.

<context1.Provider value={value1}>
  <context2.Provider value={value2}>
    <context3.Provider value={value3}>
      <context4.Provider value={value4}>
        <context5.Provider value={value5}>

        </context5.Provider>
      </context4.Provider>
    </context3.Provider>
  </context2.Provider>
</context1.Provider>
<context1.Consumer>
  {value1 => <context2.Consumer>
    {value2 => <context3.Consumer>
      {value3 => <context4.Consumer>
        {value4 => <context5.Consumer>
          {value5 => (
            null
          )}
        </context5.Consumer>}
      </context4.Consumer>}
    </context3.Consumer>}
  </context2.Consumer>}
</context1.Consumer>
Question

κ°€μž₯ μœ μš©ν•œ λŒ“κΈ€

@ 0xorial 당신은

const compose = (contexts, children) =>
  contexts.reduce((acc, [Context, value]) => {
    return <Context.Provider value={value}>{acc}</Context.Provider>;
  }, children);

λ‹€μŒκ³Ό 같이 μ‚¬μš©ν•˜μ‹­μ‹œμ˜€.

import Context1 from './context1';
import Context2 from './context2';
import Context3 from './context3';
...
import Context15 from './context15';

const MyComponent = (props) => {
  // const value1..15 = ... get the values from somewhere ;

  return compose(
    [
      [Context1, value1],
      [Context2, value2],
      [Context3, value3],
      ...
      [Context15, value15],
    ],
    <SomeSubComponent/>
  );
}

λͺ¨λ“  38 λŒ“κΈ€

곧 μΆœμ‹œ 될 Hooks APIλŠ” μ»¨ν…μŠ€νŠΈλ₯Ό μ†ŒλΉ„ν•˜λŠ” λ‹€λ₯Έ 방법을 μ œκ³΅ν•©λ‹ˆλ‹€.

https://reactjs.org/docs/hooks-reference.html#usecontext

κ°μ‚¬ν•©λ‹ˆλ‹€. ν•˜μ§€λ§Œ κ³΅κΈ‰μžλŠ” μ–΄λ–»μŠ΅λ‹ˆκΉŒ?

μ†”μ§νžˆ 말할 게. 이런 μ’…λ₯˜μ˜ κ΅¬ν˜„μ΄ λ°œμƒν•˜λ©΄ μ•„ν‚€ν…μ²˜ λ””μžμΈμ΄ 쒋지 μ•Šμ€ 것 κ°™κ³  React μ»¨ν…μŠ€νŠΈλ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šμ•„μ•Ό ν•  κ²ƒμž…λ‹ˆλ‹€.

μ•„λ‹ˆμš”, μƒˆ μ €μž₯μ†Œ μ»¨ν…Œμ΄λ„ˆλ₯Ό λ””μžμΈν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. λ°˜μ‘μ—μ„œ μ»¨ν…μŠ€νŠΈμ™€ ν•¨κ»˜ μž‘λ™ν•΄μ•Όν•©λ‹ˆλ‹€.
https://github.com/rabbitooops/rako

κ·Έ λΌμ΄λΈŒλŸ¬λ¦¬λŠ” κ³΅κΈ‰μž / μ†ŒλΉ„μžμ˜ 5 계측 κΉŠμ΄μ™€ μ–΄λ–€ 관련이 μžˆμŠ΅λ‹ˆκΉŒ?

Redux와 같은 단일 μ €μž₯μ†Œ μ†”λ£¨μ…˜ λŒ€μ‹  λ°˜μ‘ ν•  μ—¬λŸ¬ μ €μž₯μ†Œ μ£Όμž…μ„ μ§€μ›ν•˜κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€.

이 경우 μ»¨ν…μŠ€νŠΈ μ²˜λ¦¬λŠ” 이제 라이브러리의 μ‚¬μš©μžκ°€ μ•„λ‹ˆλΌ 라이브러리의 μ‚¬μš©μžμ—κ²Œ μžˆμŠ΅λ‹ˆλ‹€. κΈ°λŠ₯을 ν™œμš©ν•˜λŠ” 방법은 κ·Έλ“€μ—κ²Œ 달렀 있으며, λͺ¨λ“  κ³΅κΈ‰μžλ₯Ό ν•œκ³³μ—μ„œ 원할 경우 (μ—¬λŸ¬ 상점을 κ°–λŠ” λͺ©μ μ— μœ„λ°°λ¨) 그것이 κ·Έλ“€μ˜ μ„ νƒμž…λ‹ˆλ‹€. μ΄μƒμ μœΌλ‘œλŠ” 닀쀑 μŠ€ν† μ–΄ μ†”λ£¨μ…˜μ΄ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ μ—¬λŸ¬ λΆ„ν• μ—μ„œ κ΅¬ν˜„λ˜λ―€λ‘œ 이와 같은 쀑첩 μ»¨ν…μŠ€νŠΈλŠ” 훨씬 더 λ“œλ­…λ‹ˆλ‹€.

적어도 λ‚΄ 2 μ„ΌνŠΈ.

λ”°λΌμ„œ μ»¨ν…μŠ€νŠΈ APIλŠ” redux와 같은 단일 μ €μž₯μ†Œ μ†”λ£¨μ…˜μ—λ§Œ μΉœμˆ™ν•©λ‹ˆλ‹€.

μ „ν˜€. κ·ΈλŸ¬λ‚˜ 더 ν˜„μ‹€μ μΈ μ˜ˆμ—†μ΄ 문제λ₯Ό λ…Όμ˜ν•˜λŠ” 것도 μ–΄λ ΅μŠ΅λ‹ˆλ‹€. ν•˜λ‚˜ λ§Œλ“œμ‹œκ² μŠ΅λ‹ˆκΉŒ?

μ„Έ 개의 상점 ν…Œλ§ˆ, μ‚¬μš©μž 및 μΉ΄μš΄ν„°κ°€ μžˆλ‹€κ³  μƒμƒν•΄λ³΄μ‹­μ‹œμ˜€.

function theme(getState) {
  return {
    color: 'white',
    setColor(color) {
      this.setState({color})
    }
  }
}

function user(getState) {
  return {
    name: '',
    setName(name) {
      this.setState({name})
    }
  }
}

function counter(getState) {
  return {
    value: 0,
    increment() {
      const {value} = getState()
      this.setState({value: value + 1})
    }
  }
}

const [themeStore, userStore, counterStore] = createStores(theme, user, counter)
const [themeContext, userContext, counterContext] = createContexts(themeStore, userStore, counterStore)


class App extends React.Component {
  render() {
    return (
      <themeContext.StoreProvider>
        <userContext.StoreProvider>
          <counterContext.StoreProvider>

            <Child />

          </counterContext.StoreProvider>
        </userContext.StoreProvider>
      </themeContext.StoreProvider>
    )
  }
}

class Child extends React.Component {
  static contextType = [themeContext, userContext]
  render() {
    const [theme, user] = this.context

    /* ... */
  }
}

이상적인 ꡬ문은 λ¬΄μ—‡μž…λ‹ˆκΉŒ?

context.writeλ₯Ό μ‚¬μš©ν•˜κ³  쀑첩없이 μ—¬λŸ¬ μ»¨ν…μŠ€νŠΈ μ‚¬μš©μ„ μ§€μ›ν•©λ‹ˆλ‹€.

쀑첩없이 μ—¬λŸ¬ μ»¨ν…μŠ€νŠΈλ₯Ό μ‚¬μš©ν•˜λŠ” 것은 이미 μ§€μ›λ©λ‹ˆλ‹€. (후크 포함.)

Context.writeμ—λŠ” RFCκ°€ μ—΄λ € μžˆμŠ΅λ‹ˆλ‹€. 맀우 λ³΅μž‘ν•œ μ§ˆλ¬Έμ„ μ œκΈ°ν•˜κΈ° λ•Œλ¬Έμ— 톡과할지 μ—¬λΆ€λŠ” μ•Œ 수 μ—†μŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ RFCκ°€ μ—΄λ €μžˆλŠ” λ™μ•ˆμ΄ λ¬Έμ œμ—μ„œ μ–΄λ–€ 쑰치λ₯Ό μ·¨ν•  수 μžˆλŠ”μ§€ 잘 λͺ¨λ₯΄κ² μŠ΅λ‹ˆλ‹€. 이미 RFC λ™κΈ°μ—μžˆλŠ” 것 외에 μΆ”κ°€ ν•  것이 μžˆμŠ΅λ‹ˆκΉŒ?

μ§ˆλ¬Έν•˜κ³  μ‹Άμ–΄μš”. Reactκ°€ ν΄λž˜μŠ€μ—μ„œ μ—¬λŸ¬ μ»¨ν…μŠ€νŠΈ μ‚¬μš©μ„ μ§€μ›ν•˜μ§€ μ•ŠλŠ” μ΄μœ λŠ” λ¬΄μ—‡μž…λ‹ˆκΉŒ? Hooks APIλŠ” ν•΄κ²°ν•΄μ•Ό ν•  λ¬Έμ œκ°€ 많고 ν˜„μž¬ 맀우 λΆˆμ•ˆμ •ν•œ 것 κ°™μŠ΅λ‹ˆλ‹€.

static contextType = [themeContext, userContext]
const [theme, user] = this.context

μ—¬λŸ¬ μ»¨ν…μŠ€νŠΈλ₯Ό μžλ™μœΌλ‘œ 쀑첩 ν•  μˆ˜μžˆλŠ” StoreProviders λ₯Ό κ΅¬ν˜„ν•˜κ² μŠ΅λ‹ˆλ‹€.

const StoreProviders = constructStoreProviders(...storeContexts)

<StoreProviders>
  <Child />
</StoreProviders>

도와 μ£Όμ…”μ„œ κ°μ‚¬ν•©λ‹ˆλ‹€ Dan! :)

@rabbitooops 후크에 μ •ν™•νžˆ μ–΄λ–€ λ¬Έμ œκ°€ μžˆμŠ΅λ‹ˆκΉŒ? λ‚˜λŠ” ν”„λ‘œλ•μ…˜μ—μ„œ 후크λ₯Ό μ‚¬μš©ν•˜λ©° 우리 νŒ€μ— 잘 μž‘λ™ν•©λ‹ˆλ‹€.

그리고 이것은 μ–΄λ–»μŠ΅λ‹ˆκΉŒ? μ§€κΈˆμ€ 후크λ₯Ό μ‚¬μš©ν•΄λ„ μ•ˆμ „ν•©λ‹ˆλ‹€. @gaearon

// A library
function useStoreProviders(Component, ...contexts) {
  contexts.forEach(context => Component.useProvider(context, someValue))
}

// User code
function App(props) {
  const [theme] = useState('white')

  // Safe to use `component hook`.
  App.useProvider(themeContext, theme)
  App.useShouldComponentUpdate(() => {})

  // Meanwhile, library can also use `component hook`.
  useStoreProviders(App, storeContext1, storeContext2, storeContext3)

  // Normal hook can't use `component hook`.
  customHook()

  /* ... */
}

<App />

decorateBeforeRender(App)

@rabbitooops 단일 μŠ€ν† μ–΄μ™€ 심볼을 ν‚€λ‘œ μ‚¬μš©ν•˜μ—¬ μ—¬λŸ¬ 측의 μŠ€ν† μ–΄λ₯Ό λͺ¨λ°©ν•˜λŠ” 것은 μ–΄λ–»μŠ΅λ‹ˆκΉŒ?

data Store = Leaf Object | C Store Store

λ˜λŠ” μžλ°” μŠ€ν¬λ¦½νŠΈμ—μ„œ λΆˆμ™„μ „ν•œ λ°©μ‹μœΌλ‘œ :

const LEFT = Symbol('LEFT')
const RIGHT = Symbol('RIGHT')
function createLeafStore = return new Store({});
function createStore(leftChild :: Store, rightChild :: Store) {
  return new Store({[LEFT]: leftChild, [Right]: rightChild})
}

@TrySound 닀름 : App.useProvider

@zhujinxuan μ£„μ†‘ν•©λ‹ˆλ‹€.

@zhujinxuan 당신은 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€ μ–ΈκΈ‰λ˜μ§€ μ•Šμ€ , 예λ₯Ό :

<Subscribe to={[AppContainer, CounterContainer, ...]}>
  {(app, counter, ...) => (
    <Child />
  )}
</Subscribe>

Hooks APIλŠ” ν•΄κ²°ν•΄μ•Ό ν•  λ¬Έμ œκ°€ 많고 ν˜„μž¬ 맀우 λΆˆμ•ˆμ •ν•œ 것 κ°™μŠ΅λ‹ˆλ‹€.

μš°λ¦¬λŠ” 1 ~ 2 μ£Ό 이내에 μΆœμ‹œλ₯Ό μ€€λΉ„ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. μ—¬λŸ¬λΆ„μ΄ 그것을 μΆ”λ‘  ν•œ μ΄μœ κ°€ ν™•μ‹€ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. μ•ˆμ „μ„ μ›ν•˜μ‹ λ‹€λ©΄ 곧 μΆœμ‹œ 될 μ˜ˆμ • μ΄λ‹ˆ μž μ‹œ κΈ°λ‹€λ € μ£Όμ‹œκΈ° λ°”λžλ‹ˆλ‹€.

그리고 이것은 μ–΄λ–»μŠ΅λ‹ˆκΉŒ?

λ£¨ν”„μ—μ„œ 후크λ₯Ό ν˜ΈμΆœν•˜λŠ” 것은 일반적으둜 ν—ˆμš©λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€ ( forEach ). 이런 μ‹μœΌλ‘œ 문제λ₯Ό μΌμœΌν‚€λŠ” 것은 μ‰½μŠ΅λ‹ˆλ‹€.

useStoreProviders

useProvider 및 useShouldComponentUpdate λ‘˜ λ‹€ Hooks둜 λ¬Έμ œκ°€ μžˆμŠ΅λ‹ˆλ‹€ (이것이 React에 ν›„ν¬κ°€μ—†λŠ” μ΄μœ μž…λ‹ˆλ‹€). https://github.com/facebook/react/issues/14534#issuecomment -455411307μ—μ„œ λ‚΄ 응닡을


μ „λ°˜μ μœΌλ‘œμ΄ 문제의 μ˜λ„λ₯Ό μ΄ν•΄ν•˜λŠ” 데 어렀움을 κ²ͺκ³  μžˆμŠ΅λ‹ˆλ‹€.

닀쀑 μ»¨ν…μŠ€νŠΈ μ†ŒλΉ„λŠ” useContext ν›„ν¬λ‘œ ν•΄κ²°λ©λ‹ˆλ‹€. λ„ˆλ¬΄ λ§Žμ€ μ»¨ν…μŠ€νŠΈλ₯Ό κ΅¬λ…ν•˜κ³  λ„ˆλ¬΄ 자주 λ‹€μ‹œ λ Œλ”λ§ν•˜λŠ” ꡬ성 μš”μ†Œλ₯Ό μž‘μ„±ν•˜κΈ°κ°€ λ„ˆλ¬΄ 쉽기 λ•Œλ¬Έμ— λ°°μ—΄λ‘œ "μžλ™ν™”"ν•˜λŠ” 것은 ꢌμž₯ useContext APIκ°€ μ œκ³΅ν•˜λŠ” ꡬ성 μš”μ†Œκ°€ μˆ˜μ‹ ν•˜λŠ” μ»¨ν…μŠ€νŠΈλ₯Ό λͺ…ν™•νžˆ μ΄ν•΄ν•΄μ•Όν•©λ‹ˆλ‹€. ν•„μš”ν•œ 경우 νŠΉμ • μ»¨ν…μŠ€νŠΈλ₯Ό λͺ…μ‹œ 적으둜 μ‚¬μš©ν•˜λŠ” useMyContexts() 후크λ₯Ό μž‘μ„±ν•  수 μžˆμŠ΅λ‹ˆλ‹€. λ°°μ—΄ 길이가 λ³€κ²½λ˜λ©΄ 깨질 수 μžˆμœΌλ―€λ‘œ λ™μ μœΌλ‘œ λ§Œλ“œλŠ” 것은 ꢌμž₯ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

μ—¬λŸ¬ κ³΅κΈ‰μžλ₯Ό λ°°μΉ˜ν•˜λŠ” 것은 "보일러 ν”Œλ ˆμ΄νŠΈ"둜 λ³Ό 수 있으며 κ²°κ΅­ 이에 λŒ€ν•œ ν•΄κ²°μ±…μ΄μžˆμ„ 수 μžˆμŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ λ‚˜λŠ” λ˜ν•œ 당신이 그것을 큰 문제둜 λ³΄λŠ” 이유λ₯Ό μ΄ν•΄ν•˜μ§€ λͺ»ν•©λ‹ˆλ‹€. 이 μŠ€λ ˆλ“œμ˜ μ˜ˆλŠ” 문제λ₯Ό μ„€λͺ…ν•˜κΈ°μ— μΆ©λΆ„νžˆ ν˜„μ‹€μ μ΄μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 상단 μ–΄λ”˜κ°€μ— JSX의 μ—¬λŸ¬ λ ˆμ΄μ–΄λ₯Ό 쀑첩해도 λ‚˜μœ 것은 μ—†μŠ΅λ‹ˆλ‹€. λŒ€λΆ€λΆ„μ˜ ꡬ성 μš”μ†Œμ— 훨씬 더 κΉŠμ€ div 쀑첩이 있으며 그닀지 μ†μƒλ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

이 점에 λŒ€ν•΄ 이미 λ‹΅λ³€ ν•œ 것 κ°™μ•„μ„œ λ§ˆλ¬΄λ¦¬ν•˜κ² μŠ΅λ‹ˆλ‹€. 토둠은 μ›μœΌλ‘œ μ§„ν–‰λ©λ‹ˆλ‹€. 빠진 것이 있으면 μ•Œλ €μ£Όμ„Έμš”.

OT : @gaearon , useRender 같은 것을 μΆ”κ°€ν•˜κ±°λ‚˜ λ Œλ”λ§μ„ 더 많이 μ œμ–΄ ν•  κ³„νšμ΄ μžˆμŠ΅λ‹ˆκΉŒ? 예 :

useRender(() => <div />, [...props])

두 번째 μΈμˆ˜λŠ” useEffect 후크와 λ™μΌν•œ μ—­ν• μ„ν•©λ‹ˆλ‹€.

useMemo λŠ” λ‹Ήμ‹ μ˜ μΉœκ΅¬μž…λ‹ˆλ‹€.

https://reactjs.org/docs/hooks-faq.html#how -to-memoize-calculationsμ—μ„œ 두 번째 슀 λ‹ˆνŽ«μ„ μ°Έμ‘°ν•˜μ‹­μ‹œμ˜€.

λ‚˜λŠ” λ‹€μŒκ³Ό 같은 μ½”λ“œλ‘œ λλ‚¬μŠ΅λ‹ˆλ‹€.

function provider<T>(theProvider: React.Provider<T>, value: T) {
   return {
      provider: theProvider,
      value
   };
}

function MultiProvider(props: {providers: Array<{provider: any; value: any}>; children: React.ReactElement}) {
   let previous = props.children;
   for (let i = props.providers.length - 1; i >= 0; i--) {
      previous = React.createElement(props.providers[i].provider, {value: props.providers[i].value}, previous);
   }
   return previous;
}

그런 λ‹€μŒ λ‚΄ μ΅œμƒμœ„ 제곡 ꡬ성 μš”μ†Œμ—μ„œ :

public render() {
      return (
         <MultiProvider
            providers={[
               provider(Context1.Provider, this.context1),
               provider(Context2.Provider, this.context2),
               provider(Context3.Provider, this.context3),
               provider(Context4.Provider, this.context4),
               provider(Context5.Provider, this.context5),
            ]}
         ><AppComponents />
      </MultiProvider>
}

@gaearon

μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 상단 μ–΄λ”˜κ°€μ— JSX의 μ—¬λŸ¬ λ ˆμ΄μ–΄λ₯Ό 쀑첩해도 λ‚˜μœ 것은 μ—†μŠ΅λ‹ˆλ‹€.

λ‚˜λŠ” 그런 μ‹μœΌλ‘œ μ£Όμž…ν•˜κΈ°λ₯Ό μ›ν•˜λŠ” ~ 15 쒅속성을 가지고 있으며 15 레벨의 λ“€μ—¬ μ“°κΈ°λŠ” λ‚˜μ—κ²Œ μ˜ˆμ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. :)

@ 0xorial 당신은

const compose = (contexts, children) =>
  contexts.reduce((acc, [Context, value]) => {
    return <Context.Provider value={value}>{acc}</Context.Provider>;
  }, children);

λ‹€μŒκ³Ό 같이 μ‚¬μš©ν•˜μ‹­μ‹œμ˜€.

import Context1 from './context1';
import Context2 from './context2';
import Context3 from './context3';
...
import Context15 from './context15';

const MyComponent = (props) => {
  // const value1..15 = ... get the values from somewhere ;

  return compose(
    [
      [Context1, value1],
      [Context2, value2],
      [Context3, value3],
      ...
      [Context15, value15],
    ],
    <SomeSubComponent/>
  );
}

이 경우λ₯Ό μ²˜λ¦¬ν•˜λŠ” 라이브러리λ₯Ό 과거에 μž‘μ„±ν–ˆμŠ΅λ‹ˆλ‹€ : https://github.com/disjukr/join-react-context

react11

이것은 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ 항상 μΌμ–΄λ‚˜λŠ” μΌμž…λ‹ˆλ‹€. useContext 은 ꡬ성 μš”μ†Œμ˜ μ»¨ν…μŠ€νŠΈ 데이터 _ μ†ŒλΉ„ _에 μ ν•©ν•˜μ§€λ§Œ μ—¬λŸ¬ κ³΅κΈ‰μžκ°€μžˆλŠ” μ•±μ—μ„œ μ»¨ν…μŠ€νŠΈλ₯Ό _ 제곡 _ν•΄μ•Όν•˜λŠ” κ²½μš°μ—λŠ” 그리 쒋지 μ•ŠμŠ΅λ‹ˆλ‹€.

@alesmenzelsocialbakers μ†”λ£¨μ…˜μ˜ 폐쇄 λŒ€μ•ˆμ€ λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

const composeProviders = (...Providers) => (Child) => (props) => (
  Providers.reduce((acc, Provider) => (
    <Provider>
      {acc}
    </Provider>
  ), <Child {...props} />)
)

const WrappedApp = composeProviders(
  ProgressProvider,
  IntentsProvider,
  EntitiesProvider,
  MessagesProvider
)(App)

ReactDOM.render(<WrappedApp />, document.getElementById('root'));

단점은 각각의 νŠΉμ • Provider ꡬ성 μš”μ†Œλ₯Ό μž‘μ„±ν•΄μ•Όν•œλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€.
예:

export const ProgressProvider = ({ children }) => {
  const [progress, setProgress] = useState(0)

  return (
    <ProgressContext.Provider value={{ progress, setProgress }}>
      {children}
    </ProgressContext.Provider>
  )
}

μ„œλΉ„μŠ€ ꡬ성이 더 λ‚˜μ€ μƒνƒœ 관리 라이브러리 λ₯Ό λ§Œλ“€μ—ˆμŠ΅λ‹ˆλ‹€. λ‹€μŒμ€ κ³΅κΈ‰μž 지μ˜₯을 ν”Όν•˜λŠ” 데λͺ¨μž…λ‹ˆλ‹€ . 자유둭게 μ‹œλ„ν•˜κ±°λ‚˜ μ†ŒμŠ€ (100 μ€„μ˜ μ½”λ“œ)λ₯Ό μ½μ–΄λ³΄μ„Έμš”!

μ»¨ν…μŠ€νŠΈ κ³΅κΈ‰μžλ₯Ό μˆ˜μ§‘ν•˜λŠ” "λ²”μœ„"개체λ₯Ό λ„μž…ν•˜μ—¬ λ‹€μŒμ„ μˆ˜ν–‰ν•©λ‹ˆλ‹€.

  • μ„œλΉ„μŠ€λŠ” λ™μΌν•œ λ²”μœ„μ— μžˆλŠ”μ§€ 여뢀에 따라 κ²©λ¦¬λ˜κ±°λ‚˜ ꡬ성 될 수 μžˆμŠ΅λ‹ˆλ‹€.

    • μ„œλΉ„μŠ€λŠ” λ™μΌν•œ ꡬ성 μš”μ†Œμ— μžˆμŒμ—λ„ λΆˆκ΅¬ν•˜κ³  λ™μΌν•œ λ²”μœ„μ—μ„œ 이전 μ„œλΉ„μŠ€λ₯Ό μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

  • λ²”μœ„μ— μ˜ν•΄ μˆ˜μ§‘ 된 λͺ¨λ“  κ³΅κΈ‰μžλŠ” κ³΅κΈ‰μž 지μ˜₯을 ν”Όν•˜λ©΄μ„œ ν•œκΊΌλ²ˆμ— 제곡 될 수 μžˆμŠ΅λ‹ˆλ‹€.

λ‚˜λ„ 이것에 균열이 생겼닀. 이것은 잘 μž‘λ™ν•˜λŠ” 것 κ°™μŠ΅λ‹ˆλ‹€.

const composeWrappers = (
  wrappers: React.FunctionComponent[]
): React.FunctionComponent => {
  return wrappers.reduce((Acc, Current): React.FunctionComponent => {
    return props => <Current><Acc {...props} /></Current>
  });
}

μ‚¬μš©λ²•μ€ λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

const SuperProvider = composeWrappers([
    props => <IntlProvider locale={locale} messages={messages} children={props.children} />,
    props => <ApolloProvider client={client}>{props.children}</ApolloProvider>,
    props => <FooContext.Provider value={foo}>{props.children}</FooContext.Provider>,
    props => <BarContext.Provider value={bar}>{props.children}</BarContext.Provider>,
    props => <BazContext.Provider value={baz}>{props.children}</BazContext.Provider>,
  ]);
  return (
    <SuperProvider>
      <MainComponent />
    </SuperProvider>
  );

이 λ„μš°λ―Έλ₯Ό npm 라이브러리 react-compose-wrappers λ‘œλ„ κ²Œμ‹œν–ˆμŠ΅λ‹ˆλ‹€.

λ‹€μŒμ€ 인증 된 μ‚¬μš©μžλ₯Ό ν•„μš”ν•œ ꡬ성 μš”μ†Œλ‘œ μ „λ‹¬ν•˜λŠ” 방법을 λ³΄μ—¬μ€λ‹ˆλ‹€.

λ‚΄ μ‘μš© ν”„λ‘œκ·Έλž¨μ— λŒ€ν•΄ ν•˜λ‚˜μ˜ μƒνƒœλ₯Ό λ§Œλ“€κΈ°λ‘œ κ²°μ •ν–ˆμŠ΅λ‹ˆλ‹€. State.js νŒŒμΌμ—μ„œ 초기 μƒνƒœ, μ»¨ν…μŠ€νŠΈ, 감속기, κ³΅κΈ‰μž 및 후크λ₯Ό μ„€μ •ν–ˆμŠ΅λ‹ˆλ‹€.

import React, { createContext, useContext, useReducer } from 'react';

const INITIAL_STATE = {}

const Context = createContext();

const reducer = (state, action) => 
  action 
    ? ({ ...state, [action.type]: action[action.type] }) 
    : state;

export const Provider = ({ children }) => (
  <Context.Provider value={ useReducer(reducer, INITIAL_STATE) }>
    { children }
  </Context.Provider>
);

const State = () => useContext(Context);

export default State;

그런 λ‹€μŒ index.js νŒŒμΌμ—μ„œ κ³΅κΈ‰μžμ— λ‚΄ 앱을 λž˜ν•‘ν–ˆμŠ΅λ‹ˆλ‹€.

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from './State';
import App from './App';

ReactDOM.render(
  <React.StrictMode>
    <Provider>
      <App />
    </Provider>
  </React.StrictMode>,
  document.getElementById('root'),
);

ꡬ성 μš”μ†Œμ—μ„œ μƒνƒœλ₯Ό μ‚¬μš©ν•˜κΈ° μœ„ν•΄ 후크λ₯Ό μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€. λ””μŠ€νŒ¨μΉ˜λ₯Ό β€‹β€‹μ‚¬μš©ν•˜μ—¬ μƒνƒœλ₯Ό μ—…λ°μ΄νŠΈ ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄ μ‚¬μš©μžλ₯Ό μ–»κ±°λ‚˜ μ„€μ •ν•˜λ €λŠ” 경우.

import React, {useEffect} from 'react';
import State from './State'

const ExampleComponent = () => {
  const [{ user }, dispatch] = State(); 

  useEffect(() => {
    const getUser = async () => {
      const data = await fetch('http://example.com/user.json');  // However you get your data
      dispatch({ type: 'user', user: data });
    }
    getUser();
  }, [dispatch]);

  // Don't render anything until user is retrieved
  // The user is undefined since I passed an empty object as my initial state
  if(user === undefined) return null; 

  return(
    <p>{user.name}</p>
  );
}

export default ExampleComponent;

이런 μ‹μœΌλ‘œ λ§Žμ€ μΆ”κ°€ μ»¨ν…μŠ€νŠΈλ₯Ό μΆ”κ°€ν•˜μ§€ μ•Šκ³  ν•„μš”ν•œ λ°©μ‹μœΌλ‘œ μƒνƒœλ₯Ό ꡬ좕 ν•  μˆ˜μžˆλŠ” 자유λ₯Ό μ œκ³΅ν•˜κ³  κ³΅κΈ‰μžμ˜ κΉŠμ€ λ‘₯지λ₯Ό ν”Όν•˜λŠ” 데 λ„μ›€μ΄λœλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€.

곧 μΆœμ‹œ 될 Hooks APIλŠ” μ»¨ν…μŠ€νŠΈλ₯Ό μ†ŒλΉ„ν•˜λŠ” λ‹€λ₯Έ 방법을 μ œκ³΅ν•©λ‹ˆλ‹€.

https://reactjs.org/docs/hooks-reference.html#usecontext

클래슀 ꡬ성 μš”μ†Œμ—μ„œ μ–΄λ–»κ²Œ μ‚¬μš©ν•©λ‹ˆκΉŒ?

곧 μΆœμ‹œ 될 Hooks APIλŠ” μ»¨ν…μŠ€νŠΈλ₯Ό μ†ŒλΉ„ν•˜λŠ” λ‹€λ₯Έ 방법을 μ œκ³΅ν•©λ‹ˆλ‹€.
https://reactjs.org/docs/hooks-reference.html#usecontext

클래슀 ꡬ성 μš”μ†Œμ—μ„œ μ–΄λ–»κ²Œ μ‚¬μš©ν•©λ‹ˆκΉŒ?

클래슀λ₯Ό μž‘μ„±ν•˜μ§€ μ•Šκ³  λ‹€μ–‘ν•œ React κΈ°λŠ₯을 ν™œμš©ν•˜λŠ” 데 후크가 μ‚¬μš©λ˜μ§€ μ•ŠμŠ΅λ‹ˆκΉŒ?
즉, λ‹€μ–‘ν•œ 후크가 μˆ˜ν–‰ν•˜λŠ” λͺ¨λ“  것이 이미 ν΄λž˜μŠ€μ— μ‘΄μž¬ν•©λ‹ˆλ‹€. νŽΈλ¦¬ν•œ ꡬ문 및 μ‚¬μš© API에 λŒ€ν•΄ μ΄μ•ΌκΈ°ν•˜λŠ” 경우 λ°˜μ‘μ΄ ν΄λž˜μŠ€μ—μ„œ κΈ°λŠ₯ ꡬ성 μš”μ†Œλ‘œ μ΄λ™ν•˜λ―€λ‘œ ν•¨μˆ˜ 및 후크에 μ˜€μ‹  것을 ν™˜μ˜ν•©λ‹ˆλ‹€)

vue3와 μœ μ‚¬ν•œ APIλ₯Ό μ œκ³΅ν•˜μ—¬ 문제λ₯Ό ν•΄κ²°ν•˜λŠ” νŒ¨ν‚€μ§€λ₯Ό λ§Œλ“€μ—ˆμŠ΅λ‹ˆλ‹€.

https://github.com/TotooriaHyperion/react-multi-provide

  • λ°˜μ‘ μ»¨ν…μŠ€νŠΈμ— μΆ”κ°€ λ·° νŠΈλ¦¬κ°€ ν•„μš”ν•œ 문제λ₯Ό ν•΄κ²°ν•©λ‹ˆλ‹€.
  • λ˜ν•œ μ£Όμž… 된 κ²ƒμ˜ λ°˜μ‘μ„±μ„ λ³΄μ‘΄ν•©λ‹ˆλ‹€
  • κ³΅κΈ‰μž κ°„μ˜ ν”„λž™νƒˆ
  • WeakMap을 μ‚¬μš©ν•˜μ—¬ 쒅속성 μ €μž₯
  • 더 λ‚˜μ€ 타이프 슀크립트 지원, 쒅속성 μ£Όμž… 및 디버그 κ²½ν—˜μ„ λ‹¬μ„±ν•˜κΈ° μœ„ν•΄ 개체 λž˜ν•‘ 기호λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.

주의:

  • 데이터 μžμ²΄λ³΄λ‹€λŠ” 데이터에 λŒ€ν•œ μ•‘μ„ΈμŠ€λ₯Ό 제곡 μ»¨ν…μŠ€νŠΈμ˜ λ°˜μ‘μ„±μ— 크게 의쑴 ν•˜μ§€ μ•ŠλŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€. @gaearon 이 λ„ˆλ¬΄ λ§Žμ€ μ»¨ν…μŠ€νŠΈλ₯Ό κ΅¬λ…ν•˜μ§€ μ•ŠλŠ” 것에 λŒ€ν•΄ λ§ν•œ 것은 μ˜³μ•˜μŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ κ·ΈλŠ” μ»¨ν…μŠ€νŠΈμ˜ λ°˜μ‘μ„±μ— μ˜μ‘΄ν•˜μ—¬ 데이터 ꡬ독을 ν•΄κ²°ν•˜λŠ” 것이 잘λͺ»λœ νŒ¨ν„΄μ΄λΌκ³  μ–ΈκΈ‰ν•˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ μ˜¬λ°”λ₯Έ 방법은 μ—¬λŸ¬ μ»¨ν…μŠ€νŠΈλ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šκ³  ν•˜λ‚˜μ˜ μ»¨ν…μŠ€νŠΈμ—μ„œ 쒅속성을 μ œκ³΅ν•˜λŠ” 것 μž…λ‹ˆλ‹€. κ·Έ λ™μ•ˆ μ»¨ν…μŠ€νŠΈ λ₯Ό κ°€λŠ₯ν•œ ν•œ μ•ˆμ •μ μœΌλ‘œ μœ μ§€ν•˜μ„Έμš”.
  • λ”°λΌμ„œ 더 λ‚˜μ€ APIλ₯Ό μ›ν•˜λ©΄ 직접 μ²˜λ¦¬ν•΄μ•Όν•˜λ©° API ν”„λž™νƒˆμ„ λ§Œλ“€μ–΄μ•Όν•©λ‹ˆλ‹€. 그것이 λ‚΄ νŒ¨ν‚€μ§€μ˜ λͺ©μ μž…λ‹ˆλ‹€.

Outer.tsx

import React, { useMemo } from "react";
import { Providers, useCreateContexts, useProvide } from "../..";
import { createService, ServiceA } from "./service";

export const Outer: React.FC = ({ children }) => {
  const contexts = useCreateContexts();
  const service = useMemo(createService, []);
  useProvide(contexts, ServiceA.id, service);
  return <Providers contexts={contexts}>{children}</Providers>;
};

Inner2.tsx

import React from "react";
import { useContexts, useReplaySubject } from "../..";
import { ServiceA } from "./service";

export const Inner2: React.FC = () => {
  const [
    {
      state$,
      actions: { inc, dec },
    },
  ] = useContexts([ServiceA.id]);
  const count = useReplaySubject(state$);
  return (
    <>
      <p>{count}</p>
      <div>
        <button onClick={inc}>Increment</button>
        <button onClick={dec}>Decrement</button>
      </div>
    </>
  );
};

방법은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

interface Composable {
    (node: React.ReactNode): React.ReactElement
}

const composable1: Composable = (node)=>{
      return <someContext.Provider>{node}</someContext.Provider>
}

function Comp({children}:{children?:React.ReactNode}){
       return pipe(
             composabl1, composabl2, composable3
       )(children)
}

rxjs와 같은 λ§Žμ€ 인기 λΌμ΄λΈŒλŸ¬λ¦¬μ—μ„œ pipe ν•¨μˆ˜λ₯Ό 찾을 수 있으며이 νŒŒμ΄ν”„ 라인과 같은 μž‘μ—…μ— λŒ€ν•œ μ—¬λŸ¬ μ–Έμ–΄ μˆ˜μ€€ μ œμ•ˆλ„ μžˆμŠ΅λ‹ˆλ‹€. λ‹€λ₯Έ libλ₯Ό μ‚¬μš©ν•˜μ—¬ 'ν•΄κ²°'ν•  ν•„μš”κ°€ μ—†μŠ΅λ‹ˆλ‹€.

이 νŽ˜μ΄μ§€κ°€ 도움이 λ˜μ—ˆλ‚˜μš”?
0 / 5 - 0 λ“±κΈ‰