2016-05-05 23 views
5

Ho un componente che ha figli dello stesso tipo del componente stesso. Posso rendere anche i bambini, ma i bambini non riescono ad accedere alla loro fetta di stato. Sto usando reagire con ReduxPassa stato a componente annidato ricorsivamente in React/Redux

export class Material extends React.Component { 

    constructor(props) { 
    super(props) 
    this.renderChild = this.renderChild.bind(this) 
    this.getNestedItems = this.getNestedItems.bind(this) 
    } 

    static propTypes = { 
    parentId: PropTypes.number, 
    id: PropTypes.number.isRequired, 
    name: PropTypes.string.isRequired, 
    subtext: PropTypes.string.isRequired, 
    childIds: PropTypes.arrayOf(PropTypes.number.isRequired), 
    fileType: PropTypes.string.isRequired 
    } 

    // This is where I am having trouble. 
    // Shouldn't the props be accessible from state itself? 

    renderChild = (id, childId) => (
     <Material key={childId} 
     id={childId} 
     parentId={id} 
     name={name} 
     subtext={subtext} 
     fileType={fileType} 
     /> 
    ) 

    getNestedItems = (id, childIds) => { 
    console.log("id: " + id) 
    console.log("childIds: " + childIds) 
    var childItems = [] 
    for(var i=0; i < childIds.length; i++){ 
     var child = this.renderChild(id, childIds[i]) 
     childItems.push(child) 
    } 
    return childItems 
    } 

    render(){ 

    let childItems = [] 
    if(this.props.childIds){ 
     childItems = this.getNestedItems(this.props.id, this.props.childIds) 
    } 

    return(
     <ListItem 
     leftAvatar={<Avatar icon={fileType.length === 0 ? <FileFolder /> : <ActionAssignment />} />} 
     rightIcon={fileType.length === 0 ? <AddCircle /> : <ActionInfo />} 
     primaryText={name} 
     secondaryText={subtext} 
     initiallyOpen={fileType.length === 0} // fileType is empty if it is a folder 
     primaryTogglesNestedList={fileType.length === 0} 
     nestedItems={childItems} // one has to pass an array of elements 
     /> 
    ) 
    } 
} 

const mapStateToProps = (state, ownProps) => { 
    return { 
    id: ownProps.id, 
    name: state.Material[ownProps.id].name, 
    subtext: state.Material[ownProps.id].subtext, 
    childIds: state.Material[ownProps.id].childIds, 
    fileType: state.Material[ownProps.id].fileType, 
    } 
} 

export default connect(
    mapStateToProps 
)(Material) 

Inoltre, sto facendo uso di ListItem from Material-ui (questi sono in ultima analisi, resi all'interno di un componente List) e il mio codice è fortemente influenzato dal tree-view example nella repo ufficiale redux. Il mio stato si presenta così:

const initialState = { 
    0: { 
     id: 0, 
     name: 'Root', 
     subtext: 'Some subtext', 
     fileType: '', 
     childIds: [1] 
    }, 
    1: { 
     id: 1, 
     name: 'Child', 
     subtext: 'Child subtext', 
     fileType: 'png', 
     childIds: [] 
    } 

} 

Lo stato mostrato ha la stessa struttura come nell'esempio vista ad albero

risposta

9

Beh, se ho capito bene, si desidera che questi Material componenti per ottenere sia i dati dal negozio redux.
Se è ciò che si desidera ottenere, è necessario fornire l'accesso all'archivio del redux a ciascuno degli Material. Fondamentalmente è necessario avvolgerli tutti con lo connect HOC.
Esempio:

const MaterialContainer = connect(mapStateToProps)(Material); 

E all'interno della funzione renderChild si può usare questo MaterialContainer.

renderChild = (id) => (
    <MaterialContainer key={childId} id={childId} /> 
) 

Potete vederlo lavorare qui https://jsbin.com/taquke/edit?js,output

+1

Sì funziona! La tua risposta mi ha fatto capire quale fosse l'errore. Ho anche diviso il mio componente in un componente di presentazione e un contenitore, ma stavo rendendo il componente di presentazione come figlio nidificato invece del contenitore. – AndyFaizan

+1

Questo ha risolto lo stesso identico problema per me, grazie. Ero curioso di sapere perché questo non è gestito da 'mapStateToProps' che già associamo al componente. Anche se ho digitato la frase precedente ho capito che questo è esattamente perché abbiamo solo "mapStateToProps' per l'esportazione. I bambini annidati in modo ricorsivo invocano la funzione componente * prima * dell'esportazione, e quindi necessitano di un'applicazione separata di 'mapStateToProps'. –