У меня есть внешний (для компонента), наблюдаемый объект, который я хочу прослушивать на предмет изменений. Когда объект обновляется, он генерирует события изменения, а затем я хочу повторно визуализировать компонент при обнаружении любого изменения.
На верхнем уровне React.render
это было возможно, но внутри компонента это не работает (что имеет некоторый смысл, поскольку render
метод просто возвращает объект).
Вот пример кода:
export default class MyComponent extends React.Component {
handleButtonClick() {
this.render();
}
render() {
return (
<div>
{Math.random()}
<button onClick={this.handleButtonClick.bind(this)}>
Click me
</button>
</div>
)
}
}
Щелчок по кнопке вызывает изнутри this.render()
, но это не то, что фактически вызывает рендеринг (вы можете увидеть это в действии, потому что созданный текст {Math.random()}
не изменяется). Тем не менее, если я просто позвоню this.setState()
вместо this.render()
, он работает нормально.
Поэтому я предполагаю, что мой вопрос таков: должны ли компоненты React иметь состояние для повторного рендеринга? Есть ли способ заставить компонент обновляться по требованию без изменения состояния?
this.forceUpdate()
это правильное решение , тогда как остальные все ответы и нескольких замечаний против использованияforceUpdate()
. Тогда будет ли хорошо сказать, что вопрос еще не получил правильного решения / ответа?Ответы:
В вашем компоненте вы можете вызвать
this.forceUpdate()
принудительное повторное рендеринг.Документация: https://facebook.github.io/react/docs/component-api.html
источник
this.forceUpdate()
это не очень хорошее решение проблемы спрашивающих, это правильный ответ на вопрос, заданный в заголовке. Хотя этого, как правило, следует избегать, бывают ситуации, когда forceUpdate является хорошим решением.shouldComponentUpdate()
сделать ваше решение бесполезным.forceUpdate
следует избегать, потому что это отклоняется от мышления React. Документы React приводят пример того, когдаforceUpdate
можно использовать:Однако я хотел бы предложить идею, что даже с глубоко вложенными объектами нет
forceUpdate
необходимости. При использовании неизменного источника данных отслеживание изменений становится дешевым; изменение всегда приведет к появлению нового объекта, поэтому нам нужно только проверить, изменилась ли ссылка на объект. Вы можете использовать библиотеку Immutable JS для реализации неизменяемых объектов данных в вашем приложении.Изменение ключа элемента, который вы хотите перерисовать, будет работать. Установите ключевую опору для вашего элемента через состояние, а затем, когда вы хотите обновить установленное состояние, чтобы иметь новый ключ.
Затем происходит изменение, и вы сбрасываете ключ
Хочу отметить, что это заменит элемент, на котором меняется ключ. Примером того, где это может быть полезно, является наличие поля ввода файла, которое вы хотите сбросить после загрузки изображения.
Хотя истинный ответ на вопрос ОП был бы,
forceUpdate()
я нашел это решение полезным в различных ситуациях. Я также хочу отметить, что, если вы обнаружите, что используете,forceUpdate
вы можете пересмотреть свой код и посмотреть, есть ли другой способ сделать что-то.ПРИМЕЧАНИЕ 1-9-2019:
Выше (изменение ключа) полностью заменит элемент. Если вы обнаружите, что обновляете ключ для внесения изменений, возможно, у вас есть проблема где-то еще в вашем коде. Использование
Math.random()
в ключе заново создаст элемент с каждым рендером. Я НЕ рекомендовал бы обновлять ключ, как это, так как реагирует использует ключ, чтобы определить лучший способ перерисовать вещи.источник
key
. Во-первых, это неясно. Читатель вашего кода должен будет усердно работать, чтобы понять, почему вы используетеkey
этот способ. Во-вторых, это не более чисто, чемforceUpdate
. «Чистый» React означает, что визуальное представление вашего компонента на 100% зависит от его состояния, поэтому, если вы изменяете какое-либо состояние, он обновляется. Однако, если у вас есть несколько глубоко вложенных объектов (сценарий, в которомforceUpdate
документы приводят причину его использования), тогда использованиеforceUpdate
делает это понятным. В-третьих,Math.random()
это ... случайно. Теоретически, он может генерировать одно и то же случайное число.forceUpdate
Реактивный способ сделать это.На самом деле,
forceUpdate()
это единственное правильное решение, котороеsetState()
может не вызвать повторную визуализацию, если в ней реализована дополнительная логикаshouldComponentUpdate()
или когда она просто возвращаетсяfalse
.forceUpdate ()
SetState ()
forceUpdate()
может быть вызван из вашего компонентаthis.forceUpdate()
Hooks: Как заставить компонент перерисовать с помощью хуков в React?
Кстати: вы изменяете состояние или ваши вложенные свойства не размножаются?
источник
this.state
конструктору также должно вызвать ошибку. Может быть, не сделали этого в 2016 году; но я уверен, что теперь это так.Я избежал
forceUpdate
делать следующеетаким образом, улучшая код, ваш компонент будет УНИКАЛЬНЫМ и будет отображаться естественным образом.
источник
this.state.rows.map((item) => <MyComponent item={item} key={item.id} /> )
Если вы хотите, чтобы взаимодействовали два компонента React, которые не связаны отношениями (parent-child), рекомендуется использовать Flux или аналогичные архитектуры.
То, что вы хотите сделать, это прослушать изменения в
наблюдаемомхранилищекомпонентов, которое содержит модель и ее интерфейс, и сохранить данные, которые вызывают изменение рендеринга, какstate
вMyComponent
. Когда хранилище загружает новые данные, вы меняете состояние вашего компонента, что автоматически запускает рендеринг.Обычно вы должны стараться избегать использования
forceUpdate()
. Из документации:источник
react-redux
для автоматического сопоставления состояния магазина с реквизитами компонентов, когда это необходимо, на основе предоставленной вами функции отображения.forceUpdate
использовать крючки или HOC выбрать
Используя хуки или шаблон HOC (компонент высшего порядка) , вы можете автоматически обновлять их при изменении магазинов. Это очень легкий подход без основы.
Использование магазина Хукс способ обработки обновлений магазина
withStores HOC обрабатывает обновления магазина
Класс SimpleStore
Как пользоваться
В случае крючков:
В случае HOC:
УБЕДИТЕСЬ, чтобы экспортировать свои магазины как единое целое, чтобы получить выгоду от глобальных изменений следующим образом:
Этот подход довольно прост и работает для меня. Я также работаю в больших командах и использую Redux и MobX, и нахожу, что они тоже хороши, но просто много шаблонов. Мне просто нравится мой собственный подход, потому что я всегда ненавидел много кода за что-то, что может быть простым, когда вам это нужно.
источник
this._data = {...this._data, ...newData}
.Другие ответы пытались проиллюстрировать, как вы могли бы, но дело в том, что вы не должны . Даже хакерское решение о смене ключа не имеет смысла. Сила React заключается в том, что он отказывается от управления вручную, когда что-то должно отображаться, и вместо этого просто заботится о том, как что-то должно отображаться на входах. Затем поставьте поток входов.
Если вам нужно вручную выполнить повторный рендеринг, вы почти наверняка что-то делаете неправильно.
источник
Вы можете сделать это несколькими способами:
1. Используйте
forceUpdate()
метод:При использовании
forceUpdate()
метода могут возникнуть некоторые глюки . Одним из примеров является то, что он игнорируетshouldComponentUpdate()
метод и повторно отображает представление независимо от того,shouldComponentUpdate()
возвращает ли false. Из-за этого следует избегать использования forceUpdate (), когда это возможно.2. Передача this.state в
setState()
методСледующая строка кода устраняет проблему с предыдущим примером:
На самом деле все, что это делает, это перезаписывает текущее состояние текущим состоянием, которое запускает повторный рендеринг. Это по-прежнему не обязательно лучший способ сделать что-то, но он преодолевает некоторые глюки, с которыми вы можете столкнуться, используя метод forceUpdate ().
источник
this.setState(prevState => prevState);
Есть несколько способов перерисовки вашего компонента:
Самое простое решение - использовать метод forceUpdate ():
Еще одно решение - создать неиспользуемый ключ в состоянии (nonUsedKey) и вызвать функцию setState с обновлением этого nonUsedKey:
Или переписать все текущее состояние:
Изменение реквизита также обеспечивает повторное отображение компонента.
источник
Для полноты вы также можете добиться этого в функциональных компонентах:
Или, как многоразовый крючок:
Смотрите: https://stackoverflow.com/a/53215514/2692307
Обратите внимание, что использование механизма принудительного обновления все еще является плохой практикой, поскольку оно противоречит менталитету реагирования, поэтому его следует по возможности избегать.
источник
Мы можем использовать this.forceUpdate (), как показано ниже.
Элемент «Math.random» в DOM обновляется только в том случае, если вы используете setState для повторной визуализации компонента.
Все ответы здесь верны, дополняя вопрос для понимания ... поскольку мы знаем, что перерисовать компонент без использования setState ({}) можно с помощью forceUpdate ().
Приведенный выше код работает с setState, как показано ниже.
источник
Еще один ответ для подтверждения принятого ответа :-)
React не одобряет использование,
forceUpdate()
потому что у них, как правило, очень функциональный подход «это единственный способ сделать это». Это хорошо во многих случаях, но многие разработчики React поставляются с OO-фоном, и при таком подходе совершенно нормально слушать наблюдаемый объект.И если вы это сделаете, вы, вероятно, знаете, что вы ДОЛЖНЫ перерисовывать, когда наблюдаемые «выстрелы», и поэтому вы ДОЛЖНЫ использовать,
forceUpdate()
и это на самом деле плюс, которыйshouldComponentUpdate()
НЕ задействован здесь.Такие инструменты, как MobX, который использует OO-подход, фактически делают это под поверхностью (на самом деле MobX вызывает
render()
напрямую)источник
Я нашел, что лучше избегать forceUpdate (). Одним из способов принудительного повторного рендеринга является добавление зависимости render () от временной внешней переменной и изменение значения этой переменной по мере необходимости.
Вот пример кода:
Вызовите this.forceChange (), когда вам нужно выполнить принудительный повторный рендеринг.
источник
ES6 - я включаю пример, который был полезен для меня:
В «коротком операторе if» вы можете передать пустую функцию следующим образом:
Это, кажется, самый короткий подход.
источник
forceUpdate();
метод будет работать, но желательно использоватьsetState();
источник
Чтобы выполнить то, что вы описываете, попробуйте this.forceUpdate ().
источник
Другой способ вызова
setState
, И сохранить состояние:this.setState(prevState=>({...prevState}));
источник
forceUpdate (), но каждый раз, когда я слышал, что кто-то говорит об этом, за этим следят, чтобы вы никогда не использовали это.
источник
Вы можете использовать forceUpdate () для более подробной проверки ( forceUpdate () ).
источник