Имеющие несколько экземпляров одинаковых повторно используемых компонентов, реагирующих на одну и ту же страницу/маршрут

Мы создаем большое внешнее приложение.

Мы используем для него React-Redux

Мы создаем некоторые повторно используемые компоненты.

** Этот вопрос касается того, что на одном и том же странице/маршруте имеется несколько экземпляров одинаковых повторно используемых компонентов редукции **

Сведения о проблеме:

У нас есть компонент Headheader. Он связан с состоянием редукции.

Он прослушивает редуктор свойств заголовка SectionheaderReducer.

Поскольку у нас есть два экземпляра этого раздела на странице, оба имеют одинаковые значения, так как они связаны с одним и тем же состоянием состояния хранилища.

Как сделать конфигурируемый компонент повторного использования, основанный на регрессе, конфигурируемым. Поэтому каждый экземпляр может иметь другое значение свойства заголовка для редуктора. РазделheaderReducer

Ответы

Ответ 1

Вам нужно реализовать какой-то способ пространства имен экземпляров. Это может быть так же просто, как передача ключа для дифференциации компонентов и редукторов.

Вы можете использовать ownProps в вашей функции mapStateToProps для направления отображения в пространство имен.

const mapStateToProps = (state, ownProps) {
    let myState = state[ownProps.namepspace]
    return {
        myState.value
    }
}

Этот же метод можно использовать для передачи пространства имен в mapDispatchToProps

const mapDispatchToProps = (dispatch, ownProps) {
    return {
        myAction: (myParam) => dispatch(myAction(ownProps.namespace, myParam))
    }
}

Просто не забудьте использовать пространство имен в типе действия, чтобы редукторы не наступали

const myAction => (namespace, myParam) {
    return { type: '${namespace}/${MY_TYPE_CONSTANT}', myParam }
}

И убедитесь, что редуктор тоже находится в пространстве имен

const myReducer = (namespace) => (state = initialState, action) => {
    switch(action.type) {
        case '${namespace}/${MY_TYPE_CONSTANT}':
            return { ...state, action.myParam }
        default:
            return state
    {
}

Теперь добавьте 2 редуктора пространства имен при комбинировании редукторов

combineReducers({
    myInstance1 : myReducer('myInstance1')
    myInstance2 : myReducer('myInstance2')
}

Наконец, передайте пространство имен каждому экземпляру

render() {
    return (
        <div>
            <MyComponent namespace='myInstance1' />
            <MyComponent namespace='myInstance2' />
        </div>
    )
}

Отказ от ответственности: я являюсь основным автором следующей библиотеки.

redux-subspace может предоставить более продвинутую реализацию пространства имен без необходимости переопределения этого шаблона для каждого компонента, для которого вы хотите иметь несколько экземпляров.

Создание редукторов аналогично приведенному выше

const reducer = combineReducers({ 
    myInstance1: namespaced('myInstance1')(myReducer)
    myInstance2: namespaced('myInstance2')(myReducer)
})

Затем SubspaceProvider можно использовать для переключения состояния для каждого компонента.

render() {
    return (
        <div>
            <SubspaceProvider mapState={state => state.myInstance1} namespace='myInstance1'>
                <MyComponent />
            </SubspaceProvider>
            <SubspaceProvider mapState={state => state.myInstance2} namespace='myInstance2'>
                <MyComponent />
            </SubspaceProvider>
        </div>
    )
}

Просто убедитесь, что вы также изменили функцию mapStateToProps чтобы начать обход с поддерева, отображенного в провайдере.

const mapStateToProps = (state) {
    return {
        state.value
    }
}

Существует также компонент высшего порядка, если вы предпочитаете уменьшать вложенность.

Ответ 2

Я реализовал его по-другому, не изменяя при этом имя действия с пространством имен.

Скорее, я добавил функции, которые перехватят создателей действия и добавят meta-data к каждому действию. (после FSA) Таким образом вам не нужно менять редуктор или функцию mapStateToProps.

Также он совместим с redux-thunk.

Должна быть проста в использовании... reducer-action-interceptor

Ответ 3

Я интерпретировал вопрос, чтобы означать:

  • у вас есть данные контента в магазине (например, разделы и их названия)
  • у вас есть компоненты для рисования битов данных (например, ваш <SectionHeader/>)
  • Вы хотите отобразить более одного раздела на странице, но в настоящее время все ваши заголовки имеют одинаковый текст

Одно из возможных решений - добавить в свой магазин идею "разделов". Вы бы создали редукторы, которые управляют структурой содержимого данных. Например, состояние магазина в одно время может выглядеть так:

{ 
  sections: {
     0: {
        header: 'My section title',
        content: 'Whatever your content is'
     },
     1: {
        header: 'My other section title',
        content: 'Loads of lovely writing or hrefs to images or whatever'
     }
  }
}

"""

Тогда у вас будет "контейнерный компонент" или "компонент макета" или "умный компонент" (у них много имен), который "знает", что вы хотите использовать раздел 2 и раздел 4 на определенной странице. Как он это знает, зависит от вас. Возможно, вы жестко закодировали индексы (потому что они всегда будут одинаковыми), возможно, у вас есть правило фильтрации, возможно, у вас есть другое поле в магазине, которое определяет варианты выбора... и т.д.

Затем контейнерный компонент передает выбранный заголовок в "тупой", возможно, так:

<SectionHeader>{sections[2].header}</SectionHeader>

или же

<SectionHeader title={sections[2].header} />