Контекст реагирования: потребитель не запускает обработчики от провайдера - PullRequest
0 голосов
/ 22 января 2020

У меня следующая ситуация: поставщик, предоставляющий состояние для моих компонентов: ChildProvider и множество потребителей: ChildrenComponent, ChildrenListComponent et c. В провайдере я установил обработчики, чтобы иметь дело с добавлением, редактированием и удалением элементов в списке, также я установил обработчики, имеющие дело с показывать или скрывать компонент и список детей для каждой системы. Я могу видеть список, предоставленный поставщиком точно так, как ожидалось, но обработчики не работают. Например, в компоненте дочернего списка я отправил обработчик, чтобы показать AddChildComponent в соответствии с нажатием кнопки в пределах TitleComponent, но я не вижу ChildrenAddComponent рендеринга и не знаю почему. Что мне здесь не хватает? Любые другие обработчики, с которыми он работает: (

MilesContext

import React from 'react';

const MilesContext = React.createContext();

export default MilesContext;

ChildrenProvider

import MilesContext from './MilesContext';
import React, {Component} from 'react';

export default class ChildProvider extends Component {

    state = {
        child: {
            childList : [{
                id: 1,
                name: "Sheldon Lee Cooper",
                birthDate: "01-25-2014",
                gender: "male"

            },
            {
                id: 2,
                name: "Amy Farah Fowler",
                birthDate: "06-25-2017",
                gender: "female"
            }],
            showComp : false,
            handleShow : this.handleShowComponent,
            handleHide : this.handleHideComponent,
            handAddChildren : this.handleAddChildrenToList,
            handleEditChildren : this.handleEditChildrenFromList,
            handleDeleteChildren: this.handleDeleteChildrenFromList
        }
    }

    handleShowComponent = () => {
        console.log("eliete")
        this.setState({ showComp : true})
    }
    handleHideComponent = () => this.setState({ showComp : false})
    handleAddChildrenToList = (child) => {
        child.id = this.state.child.childList.length + 1
        this.setState({
            childList: [...this.state.child.childList, child]
        })
    }
    handleEditChildrenFromList = (editedChild) => {
        const editedList = this.state.child.childList.map(child => (child.id === editedChild.id ? editedChild : child))
        this.setState({childList: editedList})
    }
    handleDeleteChildrenFromList = (deletedChild) => {
        const editedList = this.state.child.childList.filter(child => child.id !== deletedChild.id)
        this.setState({childList: editedList})
    }

    render() {
        return (
            <MilesContext.Provider
                value={{
                    child: this.state.child,
                    handleShowComponent : this.state.child.handleShow,
                    handleHideComponent : this.state.child.handleHide,
                    handleAddChildrenToList : this.state.child.handAddChildren,
                    handleEditChildrenFromList : this.state.child.handleEditChildren,
                    handleDeleteChildrenFromList: this.state.child.handleDeleteChildren
                }}>
                {this.props.children}
            </MilesContext.Provider>
        );
    }

}

ChildrenComponent

import React from 'react';
import MilesContext  from '../../context/MilesContext';
import ChildrenList from './ChildrenListComponent';
import ChildrenAddComponent from './ChildrenAddComponent';

const Children = () => (
    <MilesContext.Consumer>
        {(value) => (
            <>
                <ChildrenList />
                { value.child.showComp ?
                    <ChildrenAddComponent/>
                    :
                    null
                }
            </>
        )}
    </MilesContext.Consumer>
)

export default Children;

ChildrenComponent

import React from 'react';
import MilesContext  from '../../context/MilesContext';
import ChildrenItem from './ChildrenItem';
import TitleComponent from '../TitleComponent';

const ChildrenList = (props) => (
    <MilesContext.Consumer>
        {value => (
            <div className="container-wrapper">
                <div className="row">
                    <TitleComponent 
                        title={ "Children" } 
                        icon={ "fa fa-plus-circle fa-2x justify-content-center mx-auto top-right" }
                        showComponent={ value.child.handleShowComponent } 
                    />
                </div>
                <div className="row justify-content-center">
                    { value.child.childList.length === 0 ?
                        <div className="col-sm-3">
                            <div className="card bg-warning text-center pt-3">
                                <p>No child added!</p>
                            </div>
                        </div>
                        : 
                        <div className="col-sm-6">
                            <ul className="list-unstyled">
                                { value.child.childList.map(child => {
                                    console.log(value.child.handleDeleteChildren)
                                    return (
                                        <li key={ child.id }>
                                            <ChildrenItem
                                                child={ child }
                                                handleEditChildren={ value.child.handleEditChildren }
                                                handleDeleteChildren={ value.child.handleDeleteChildren }
                                            />
                                        </li>
                                    )})
                                }
                            </ul>
                        </div>
                    }
                </div>
            </div>
        )}
    </MilesContext.Consumer>
)

export default ChildrenList;

TitleComp onet

import React from 'react';
import MilesContext  from '../context/MilesContext';

export default function TitleComponent(props) {

    return (
        <MilesContext.Consumer>
            { value => (
                <div className="col-sm-12 title-container">
                    <h3><i className="fa fa-user fa-1x mr-3"></i>{props.title}</h3>
                    <i className={props.icon} onClick={() => props.showComponent}></i>
                    <hr/>
                </div>
            )}
        </MilesContext.Consumer>
    );
}

1 Ответ

0 голосов
/ 22 января 2020

Проблема исходит от "different state level"

handleShowComponent = () => {
    console.log("eliete")
    this.setState({ showComp : true})
}

это работает на this.state.showComp не на this.state.child.showComp вы [вероятно] ожидаете здесь

            { value.child.showComp ?

или здесь

        <MilesContext.Provider
            value={{
                child: this.state.child,

Если вы хотите обновить вложенный объект, не забывайте не изменять существующий объект (child), а возвращать новый:

setState( { child: {...this.state.child, showComp: true } })

Подробнее об этом здесь

Google для других setState примеров глубокого обновления объектов ... или связанных с избыточностью ... применяются те же правила (мелкие сравнение).

...