Рендеринг компонента при изменении состояния в React

У меня есть приложение, которое вызывает две функции; Моя корзина и Мои товары. Я пытаюсь сделать так, чтобы при вызове кнопки, отображаемой в MyItems, вызывался метод внутри основного компонента приложения (родительского) и изменялось состояние, но по какой-то причине он не менял значение в диапазоне MyCart.

Мой код ниже - это то, что я пытаюсь сделать, но он не работает, и я не могу понять, почему.

class ShopRemake extends React.Component {
    constructor() {
        super();
        this.state = {
            total: 0
        }

        this.changeTotal = this.changeTotal.bind(this);
    }

    changeTotal() {
        this.setState(prevState => {total: ++prevState.total});
        console.info(this.state);
    }

    render() {
        return (
            <React.Fragment>
                <MyItem changeTotal = {this.changeTotal}/>
                <MyCart total = {this.state.total}/>
            </React.Fragment>
        );
    }
}

function MyItem(props) {
    return (
        <button onClick = {props.changeTotal}> Click Me </button>
    );
}

function MyCart(props) {
    return (
        <span> Total Items: {props.total} </span>
    );
}

Я хочу, чтобы после нажатия кнопки диапазон внутри MyCart обновлялся соответствующим образом.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
70
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы должны заключить литерал возвращаемого объекта в круглые скобки в своих стрелочных функциях. В противном случае фигурные скобки будут считаться обозначением тела функции. Следующие работы:

p => ({ foo: 'bar' })

Итак, вызов setState в changeTotal:

changeTotal() {
    this.setState(prevState => {total: ++prevState.total});
    console.info(this.state);
}

Следует заменить следующим:

changeTotal() {
    this.setState(prevState => ({total: ++prevState.total}));
    console.info(this.state);
}

Кроме того, setState является асинхронным, вам нужно либо дождаться его (не рекомендуется), либо использовать обратный вызов в качестве второго параметра, чтобы увидеть результирующее состояние:

changeTotal() {
    this.setState(
        prevState => ({total: ++prevState.total}),
        () => { console.info(this.state) }
    );
}

РЕДАКТИРОВАТЬ :

Обратите внимание: два приведенных ниже компонента в вашем коде могут быть преобразованы в функции стрелок для получения точно такого же результата, но при этом их будет легче читать:

const MyItem = ({ changeTotal }) => <button onClick = {changeTotal}> Click Me </button>

const MyCart = ({ total }) => <span> Total Items: {total} </span>

И вы также можете преобразовать changeTotal в функцию стрелки, чтобы избежать необходимости привязывать ее в своем конструкторе.

Эй, спасибо, чувак, я понятия не имею, как это работает, но это сработало :D

Valchy 06.02.2019 14:23

Это потому, что JS будет рассматривать скобки: {} после объявления функции как блоки инструкций, а не объект JSON. С помощью скобок вы сообщаете своему браузеру, что это объект. Рад, что смог помочь

Treycos 06.02.2019 14:24

@Treycos, я думаю, в вашем редактировании есть путаница. MyItem и MyCart уже являются функциями без сохранения состояния в исходном коде. Вы не делаете их безгражданскими, вы просто конвертируете их в стрелочные функции. Это не имеет преимущества в производительности, но легче для глаз.

Harun Akgün 06.02.2019 15:18

@HarunAkgün Ой, вы правы, я думал, что видел где-то класс, прежде чем менять их. Так что в основном да, изменение их с классических на стрелочные функции только сделало их более удобными для глаз.

Treycos 06.02.2019 15:20

Да, не беспокойтесь, это был просто пример в моем коде, я изменил его соответствующим образом.

Valchy 06.02.2019 20:40

Ваш setState не возвращает здесь объект. Попробуйте изменить свой метод changeTotal на этот

changeTotal() {
     this.setState(prevState => ({ total: prevState.total + 1 }), () => 
     console.info(this.state));
}

Методы setState являются асинхронными, если вы хотите зарегистрировать их значение, сделайте это с помощью обратного вызова.

ага, теперь разобрался. В любом случае, спасибо, но, к сожалению, вы ответили вторым, поэтому я не могу поставить галочку :/

Valchy 06.02.2019 14:33

Другие вопросы по теме