У меня действительно странная проблема. Я имею в виду, на самом деле для меня. Это не проблема типа «использовать setState вместо this.state». Я работаю над приложением для планирования поездок. Я использую ContextAPI, который предоставляет информацию для входа и пользовательские данные (зарегистрированные пользовательские поездки и т. Д.) Для всего приложения. Компонент «Расписание», отображающий расписание поездок по дням, является контекстным подписчиком. Теперь я хочу удалить один из дней поездки (день, также подписка на контекст - это компонент, отображаемый компонентом расписания в списке расписания). И тут происходит волшебство:
когда я делаю это сразу после входа в приложение, все работает нормально. Но когда я обновлю страницу и удалю другой день, состояние контекста (которое, как я уже сказал, содержит все данные, включая список дней по расписанию) изменится (проверено с помощью инструментов разработчика), но компонент расписания не перерисовывает себя, поэтому удаленный элемент остается видимым. Но, как я уже сказал, состояние меняется, и все работает нормально без обновления страницы перед удалением операции. Также, когда я переключаюсь на другую вкладку («Расписание» - это всего лишь одна из вкладок, у меня есть, например, вкладка «Затраты и примечания» на панели навигации, отображающие компоненты «Затраты и заметки»), а затем возвращаюсь на вкладку «Расписание», которую он повторно отображает, и все остальное. выглядит нормально, компонент отображает информацию в соответствии с состоянием контекста.
Код работает следующим образом: удаление (функция контекста) запускается щелчком значка удаления в Day.js (контекстный подписчик), Day.js отображается с помощью Schedule.js (также контекстный подписчик).
В Context.js
... context functions ...
    //WRAPPER FOR DELETE FUNCTIONS
    delete(url, deleteFunc) {
        this.requestsApi.request(url, "DELETE", null)
        .then(response => {
            if(response.status===204) {
                deleteFunc();
            } else {
                this.toggleRequestError(true);
            }
        })
        .catch( err => {
            console.log(err);
            this.toggleRequestError(true);
        });
    }
    deleteDay = (id, tripId) => {
        let newTrip = this.state.userData.trips.find((trip => trip.id === 
         tripId));
        newTrip.days = newTrip.days.filter(day => day.id !== id)
        this.updateTrip(newTrip);
    }
    updateTrip = (newTrip) => {
        let trips = this.state.userData.trips;
        this.setState(prevState => ({
            userData : {
                ...prevState.userData,
                trips: trips.map(trip => {
                    if(trip.id !== newTrip.id)
                        return trip;
                    else
                        return newTrip;
                    })
                }
            }
        ));
    }
...
В Schedule.js
... in render's return ...
<ul>
    {this.trip.days.map((day,index) => {
         return <DayWithContext 
            inOverview={false} 
            key={index} 
            number={index} 
            day={day} 
            tripId={this.trip.id}    
         />
     })}
</ul>
....                 
В Day.js (значок удаления)
...
<img 
    src={Delete} 
    alt="Delete icon" 
    className="mr-2" 
    style={this.icon}
    onClick={() => {
             this.props.context.delete(
             `/days/${this.props.day.id}`, 
             () => this.props.context.deleteDay(this.props.day.id, 
                   this.props.tripId)
             );
    }}
/>
...
Кто-нибудь знает, что происходит и почему расписание не может быть повторно отображено после удаления, выполненного после обновления страницы? И даже если состояние контекста изменится? Единственная идея, которая у меня есть на данный момент, заключается в том, что это какая-то ошибка ...
// ОБНОВЛЕНИЕ В компоненте Расписание, в функции componentWillReceiveProps () я консоль логирую props.context.trip [0] .day [0] - первый день. Это не объект, а просто текст, поэтому он не оценивается, «когда я нажимаю на него в консоли». Прежде чем я его удалю, консоль регистрирует первый элемент. После того, как я удалю его, консоль регистрирует второй элемент (так что теперь это первый элемент в списке), так что реквизиты, заданные расписанию, меняются, но рендеринг не запускается ... Что, черт возьми, там происходит?
// ОБНОВЛЕНИЕ 2 Я также заметил, что когда я переключаюсь на компонент «Расписание» из другого компонента, он работает хорошо (например, я обновляю страницу в конечной точке / cost, затем щелкаю вкладку «Расписание» в меню панели навигации, что ведет к / schedule). Но когда я обновляю страницу при включении / расписании конечной точки, возникает эта «ошибка», и компонент не выполняет повторный рендеринг.
// Рендеринг из контекста:
...
    render() {        
        const {
            isLoggedIn,
            wasLoginChecked,
            userData,
            isLogoutSuccesfulActive,
            isLogoutUnSuccesfulActive,
            isDataErrorActive,
            isRequestErrorActive,
            isDataLoaded
        } = this.state;
        const context =  {
            isLoggedIn,
            wasLoginChecked,
            isLogoutSuccesfulActive,
            isLogoutUnSuccesfulActive,
            isDataErrorActive,
            isRequestErrorActive,
            userData,
            isDataLoaded,
            requestsApi : this.requestsApi,
            toggleLogin : this.toggleLogin,
            checkLogin: this.checkLogin,
            setUserData: this.setUserData,
            loadData: this.loadData,
            addTrip: this.addTrip,
            delete: this.delete,
            deleteDay: this.deleteDay,
            deleteActivity: this.deleteActivity,
            deleteTrip: this.deleteTrip,
            updateTrip: this.updateTrip,
            uncheckLogin: this.uncheckLogin,
            toggleLogoutSuccesful: this.toggleLogoutSuccesful,
            toggleLogoutUnSuccesful: this.toggleLogoutUnSuccesful,
            toggleRequestError: this.toggleRequestError,
            toggleDataError: this.toggleDataError
        };
        return (
            <Context.Provider value={context}>
                {this.props.children}
            </Context.Provider>
        )
    }
}
export const Consumer = Context.Consumer;
------------- Контекст HOC:
export default function withContext(Component) {
    return function ContextComponent(props) {
        return (
            <Context.Consumer>
                {context => <Component {...props} context={context} />}
            </Context.Consumer>
    );
    }
}
 
                                                                     
                                                                     
                                                                    
newTripпосле кода, вы также измените поездку в своем состоянии. Попробуйте этот код:const arr = [{foo: "bar"}]; const newArr = Array.from(arr); newArr[0].foo = "baz"; console.log(arr[0].foo);(извините за форматирование, комментарии не позволяют использовать красивое форматирование) Видите ли,Array.fromне создает новые объекты, а просто копирует ссылки на исходные. Вам нужно сделать то же самое, что я показываю в своем ответе, вам нужно создать новый объект для вашегоnewTrip. 31.08.2019day.idв качестве ключа для вашего компонента:key={day.id}31.08.2019shouldComponentUpdate. Единственное, что вам следует знать оshouldComponentUpdate, это то, что первым параметром будетnewProps, а старые реквизиты могут получить доступ черезthis.props. Итак, если вы определите что-то вродеgetTripвнутриshouldComponentUpdate, вы получите только старыйtrip. 01.09.2019