ReactJS: Чому передача початкового стану компонента prop анти-шаблоном?


79

Я створив невелику інформаційну панель ReactJS за допомогою SocketIO для поточних оновлень. Незважаючи на те, що у мене оновлюється інформаційна панель, мене хвилює, що я не зовсім впевнений, чи правильно це зробив.

Найбільше мене зловживає Props у getInitialState як пост -шаблон . Я створив інформаційну панель, яка отримує поточні оновлення від сервера, не вимагаючи жодної взаємодії користувача, окрім завантаження сторінки. З того, що я прочитав, this.stateповинно містити речі, які визначатимуть, чи потрібно компонент переобробляти, і this.props.... поки що не знаю.

Однак, коли ви спочатку дзвоните React.render(<MyComponent />, ...), ви можете пройти лише реквізит. У моєму випадку я отримую всі дані з сервера, тому початковий реквізит у this.stateбудь-якому випадку просто опиняється. Тож усі мої компоненти мають щось подібне:

getInitialState: function() {
    return {
        progress: this.props.progress,
        latest_update: this.props.latest_update,
        nearest_center: this.props.nearest_center
    }
}

Що, якщо я не неправильно витлумачив згадану публікацію в блозі, є анти-шаблоном. Але я не бачу жодного іншого способу вливання стану в Компонент, і я не розумію, чому це анти-шаблон, якщо я не перекреслюю всі свої реквізити, щоб initialна них покластися . Якщо що, я відчуваю, що це анти-шаблон, тому що тепер я повинен відстежувати більше змінних, ніж раніше (тих, що додаються initialта тих, хто не має).


1
У 2017 році Facebook демонструє використання реквізиту для встановлення початкового стану у своїй документації: responsejs.org/docs/react-component.html#constructor
Ромер

1
Посилання @ Rohmer містить посилання на Вам, ймовірно, не потрібен похідний стан , в якому детально обговорюються альтернативи та чого слід уникати.
ToolmakerSteve

Відповіді:


94

Застереження : Коли я відповів на це запитання, я вчився / намагався впровадити ванільний потік, і був трохи скептичний щодо цього. Пізніше я переніс усе на Redux. Отже, порада: просто йдіть з Redux або MobX. Швидше за все, вам навіть більше не знадобиться відповідь на це запитання (за винятком науки).

Передача початкового стану компоненту як a propє анти-шаблоном, оскільки getInitialStateметод викликається лише перший раз, коли компонент відображається. Це означає, що якщо ви повторно рендеріруєте цей компонент, передаючи інше значення як a prop, компонент не реагуватиме відповідно, оскільки компонент буде зберігати стан з першого разу, коли він був відтворений. Це дуже схильне до помилок.

І ось що вам слід зробити:

Постарайтеся зробити свої компоненти якомога бездержавнішими. Безкомпонентні компоненти легше перевірити, оскільки вони виводять результат на основі введення . Просто так.

Але ей .. дані моїх компонентів змінюються .. Я не можу зробити їх без громадянства

Так, для більшості з них ви можете. Для цього виберіть зовнішній компонент, який буде державним органом. На вашому прикладі ви можете створити Dashboardкомпонент, що містить дані, і Widgetкомпонент, який повністю не має стану. Він Dashboardвідповідає за отримання всіх даних, а потім надання кількох, Widgetsякі отримують все необхідне props.

Але мої віджети мають певний стан .. користувач може їх налаштувати. Як зробити їх без громадянства?

Ви Widgetможете виставляти події, які при обробці спричиняють Dashboardзміну стану, що міститься , що спричиняє Widgetповторне відображення кожного. Ви створюєте "події" у своєму Widget, отримуючи propsфункцію.

Гаразд, отже, інформаційна панель зберігає стан, але як мені передати початковий стан?

У вас є два варіанти. Найбільш рекомендованим є те, що ви робите виклик Ajax у Dashboard getInitialStateметоді, щоб отримати початковий стан із сервера. Ви також можете використовувати Flux , що є більш складним способом управління даними. Потік - це скоріше шаблон, а не реалізація. Ви можете використовувати чистий Flux з реалізацією Facebook на Dispatcher, але ви можете використовувати сторонні реалізації, такі як Redux , Alt або Fluxxor .

Крім того , ви можете передати це початковий стан , як propдо Dashboard, явно заявляючи , що це лише початковий стан .. як initialData, наприклад. Однак, якщо ви вибрали цей шлях, ви не зможете передати йому інший початковий стан за кордоном, оскільки він "запам'ятає" стан після першого відтворення.

OBS

Ви не зовсім праві у своїх визначеннях.

Стан використовується для зберігання змінних даних, тобто даних, які будуть змінюватися протягом життєвого циклу компонента. Зміни у стані повинні вноситися за допомогою setStateметоду, що призведе до повторного відтворення компонента.

Реквізит використовується для передачі незмінних даних до компонентів. Вони не повинні змінюватися протягом життєвого циклу компонента. Компоненти, що використовують лише реквізит, не мають громадянства.

Це відповідне джерело про те, "як передати початковий стан компонентам".


це описано дуже добре, але ... як завжди є "але". Що робити, якщо у мене є компонент, який отримує масив зображень і створює дочірні компоненти з ескізами та подією onlick, що має змінити велике зображення в цьому компоненті. Зображення не у стані, тому я не можу використовувати інший компонент для його підтримки. Зображення локальні, і мені потрібен якийсь локальний штат для управління, який повинен відображатися як велике зображення. Я хотів би використовувати реквізит у стані, але отримати попередження: setState (...): Не вдається оновити під час переходу існуючого стану (наприклад, всередині render). Методи візуалізації повинні бути чистою функцією властивостей та стану.
Канія

10
отже, будь-яка думка щодо використання componentWillReceiveProps(nextProps)для встановлення стану?
Алехандро

1
КомпонентWillRecieveProps () застарілий станом на 16.3, тому ... Ні. Не використовуйте його.
Реп,

@Alejandro - Ви , напевно , не потрібні висновки стан є поглибленим поясненням пасток у використанні ( НЕ рекомендується) componentWillReceiveProps, або його (не рекомендується) заміна, getDerivedStateFromProps. Підсумок: стаття демонструє кілька альтернативних рішень, які не викликають жодного з цих методів, і пояснює, чому використовувати ці альтернативи замість цього.
ToolmakerSteve
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.