2017-01-09 13 views
0

Скажет, у меня есть функциональный Реагировать компонент представления, например, так:Что такое надежный способ рендеринга динамического количества дочерних компонентов React, используя шаблон компонентов контейнера Redux?

const Functional = (props) => { 
    // do some stuff 

    return (
    <div> 
     // more HTML based on the props 
    </div> 
); 
} 

Functional.propTypes = { 
    prop1: React.PropTypes.string.isRequired, 
    prop2: React.PropTypes.string.isRequired, 
    // ... 
}; 

Если я использую Redux и по образцу компоненты контейнера, что было бы лучшим способом, чтобы сделать динамический ряд этих <Functional/> компонентов внутри компонент оболочки, основанный на элементах внутри массива (который находится внутри моего состояния Redux)?

E.g. Мой Redux состояние может выглядеть следующим образом:

{ 
    functionalItems: [ 
    { 
     prop1: 'x1', 
     prop2: 'y1', 
     // ... 
    }, 
    { 
     prop1: 'x2', 
     prop2: 'y2' 
    }, 
    // ... more items 
    ], 
    // ... 
} 

Таким образом, каждый элемент в массиве functionalItems должен соответствовать <Functional/> компоненту, который все получает оказанное рядом друг с другом.

Это второй раз, когда я столкнулся с этой проблемой, поэтому я надеюсь, что это достаточно распространено, что есть хорошее решение там.

Я выложу решения, которые я могу придумать (но которые имеют нежелательные черты), как ответы на этот вопрос.

+0

Можете ли вы опубликовать пример ввода и вывода html, который вы ожидаете получить? – Luke101

+0

@ Luke101 это шаблонный тип вопроса, а не «Я пытаюсь заставить XYZ работать, но я не могу, не могли бы вы помочь мне? ?» вид вопросов. – pleasedesktop

ответ

1

Я хотел бы предложить вам пройти весь массив компонент обертки например:

const mapStateToProps = (state) => ({ 
    items: getFunctionalItems(state), 
    // ... 
}); 

, а затем в вашем Wrapper.jsx, сделать это следующим образом:

const Wrapper = (props) => { 

    const elements = props.items.map((item, index) => { 
    <Functional prop1={ item.prop1 } prop2={ item.prop2 } ... 
     key={ ... /* you can use index here */ }/> 
    }); 

    return (
    <div> 
     { elements } 
    </div> 
); 

}; 

... где getFunctionalItems() является функцией сбруи, которая является каноническим средством доступа к функциональным элементам из состояния.

Таким образом, вы можете обрабатывать изменения в структуре состояния или другой макет рендеринга. (ergo более надежный (я думаю)). И это больше похоже на принцип единой ответственности.

+0

Что было бы полезно для передачи в массиве напрямую, если вы даже не используете элементы напрямую, т. Е. Вы все еще используете 'getPropValueX()' функции? – pleasedesktop

+0

^Извините, забыл изменить это. :) –

+0

Нет проблем, я думал, что может быть так. Это подход чище, но на самом деле он более хрупкий. Вы заявляете, что это было бы устойчиво к изменениям в структуре штата, но я бы сказал противоположное. Вы полагаетесь на структуру штата, в отличие от моего решения, чего нет. – pleasedesktop

0

Решение Описание

  • Создать функциональный компонент представления обертку, которая принимает в количестве и функции для извлечения значения <Functional/> гребного винта.
  • Создайте контейнерный компонент, который подключается к этому новому компоненту-обертки и передает количество (на основе состояния Redux) и функции доступа для получения значений поддержки <Functional/>.

Пример кода

Wrapper.jsx:

const Wrapper = (props) => { 

    const elements = []; 

    for (let i = 0; i < props.quantity; i++) { 
    elements.push(
     <Functional prop1={ getPropValue1(i) } prop2={ getPropValue2(i) } ... 
        key={ ... }/> 
    ); 
    } 

    return (
    <div> 
     { elements } 
    </div> 
); 
}; 

Wrapper.propTypes = { 
    quantity: React.PropTypes.number.isRequired, 
    getPropValue1: React.PropTypes.func.isRequired, 
    getPropValue2: React.PropTypes.func.isRequired, 
    // ... 
}; 

ContainerComponent.js:

const mapStateToProps = (state) => ({ 
    quantity: state.functionalItems.length, 
    getPropValue1: (index) => state.functionalItems[index].prop1, 
    getPropValue2: (index) => state.functionalItems[index].prop2, 
    // ... 
}); 

const ContainerComponent = connect(mapStateToProps)(Wrapper); 
+0

Это «лучшее» решение, которое я могу придумать, но оно все еще кажется хрупким/неуклюжим для меня. Есть ли более элегантный подход? – pleasedesktop