2016-05-05 18 views
5

Mam komponent, który ma dzieci tego samego typu, co sam komponent. Mogę także oddać dzieci, ale dzieci nie mogą uzyskać dostępu do swojego kawałka państwa. Używam reagują z ReduxPrzekaż stan rekursywnie zagnieżdżonego komponentu w 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) 

Również jestem wykorzystanie ListItem from Material-ui (są ostatecznie świadczonych wewnątrz składnika List) i mój kod jest pod silnym wpływem z tree-view example w oficjalnym Redux repo. Mój stan wygląda następująco:

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

} 

stanie pokazanym ma taką samą strukturę jak w przykładzie widoku drzewa

Odpowiedz

9

dobrze, jeśli dobrze rozumiem prawo, chcesz te Material składniki, aby uzyskać to dane z sklep redux.
Jeśli chcesz to osiągnąć, musisz zapewnić dostęp do sklepu redux do każdego z Material. Zasadniczo musisz owinąć je wszystkie za pomocą HOC connect.
Przykład:

const MaterialContainer = connect(mapStateToProps)(Material); 

A wewnątrz funkcji renderChild chcesz wykorzystać ten MaterialContainer.

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

Widać to działa tutaj https://jsbin.com/taquke/edit?js,output

+1

Tak to działa! Twoja odpowiedź uświadomiła mi, co to za błąd. Również podzieliłem mój komponent na komponent prezentacji i kontenera, ale renderowałem komponent prezentacji jako zagnieżdżone dziecko zamiast kontenera. – AndyFaizan

+1

To rozwiązało dokładnie ten sam problem, dzięki. Byłem ciekawy, dlaczego nie jest to obsługiwane przez 'mapStateToProps', które już dołączamy do komponentu. Chociaż, jak pisałem w poprzednim zdaniu, zdałem sobie sprawę, że jest to dokładnie dlatego, że mamy tylko "mapStateToProps" do eksportu. Rekursywnie zagnieżdżone elementy potomne wywołują funkcję składową * przed * eksportem, a zatem potrzebują osobnej aplikacji 'mapStateToProps'. –