Какого черта setState () иногда не работает?

Как заставить виджет перерисовываться во Flutter?

… И почему Flutter пытается переработать состояние виджетов?



Сколько раз вы вызывали setState (), но на экране ничего не менялось, хотя внутреннее состояние виджета изменилось?
Я знаю, что много раз :)

Итак, простой экран с текстом, который отображает текущее значение, которое увеличивается каждый раз, когда пользователь нажимает кнопку. Это было бы несложно, если бы мы использовали текстовый виджет без сохранения состояния - ›он будет перестраиваться каждый раз, когда пользователь нажимает кнопку.

Но наша реализация текста выглядит так:

Мы берем начальное значение из виджета и сохраняем его локально в объекте State во время выполнения initState (). initState () вызывается только в первый раз, когда пользователь нажимает кнопку, и никогда больше, поэтому мы не видим изменений на экране. Но почему это происходит?

На самом деле Flutter работает именно так: пытается сохранить состояние виджета с отслеживанием состояния.

Виджеты неизменяемы, что означает, что их необходимо перестраивать для каждого setState (), но их состояние сохраняется до тех пор, пока в той же позиции в дереве (дереве элементов) не появится новый виджет с другой ТИП или другой КЛЮЧ!

В нашем примере наш виджет находится в том же месте, что и раньше (тот же виджет, поэтому, конечно, того же типа), и мы не использовали ключи, поэтому с точки дерева элементов , ничего не изменилось, и состояние сохраняется.

Мы не хотим менять тип нашего виджета, но можем ввести ключи! :)

При добавлении UniqueKey во время setState () корневого виджета состояние MyStatefulText будет восстановлено с нуля, а его initState () будет вызываться каждый раз, когда пользователь нажимает кнопку.

Ура, работает! :)

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

Если вы хотите выполнять перерисовку только в особых случаях, вы можете использовать ValueKey. Установив этот тип ключа, ваша перерисовка будет выполняться, только если значение этого ключа изменится.

redrawObject is a property inside _MyStatefullTextState class!

По сути, мы при каждом втором нажатии перерисовываем MyStatefulText. А сейчас это выглядит так:

Заинтересованы в присоединении к Medium по моей реферальной ссылке? 💙
Спасибо! :)



… И если вам понравилась эта статья, пожалуйста, несколько раз хлопните в ладоши :)