Форум программистов, компьютерный форум, киберфорум
React/ReactJS
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.75/8: Рейтинг темы: голосов - 8, средняя оценка - 4.75
4 / 4 / 1
Регистрация: 26.03.2023
Сообщений: 153

Как правильно передать setState от ребенка к родителю

05.04.2024, 21:41. Показов 2557. Ответов 37

Студворк — интернет-сервис помощи студентам
Всем привет. Мне нужно передать функцию setImages из компонента CardSlider (ребенка) компоненту Card (родителю). Вот часть моего кода:
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
let Card = () => {
// Много другого кода
 
  let setImagesFunction = false
 
  let CardSlider = () => {
    let [images, setImages] = useState(null)
  
    useEffect(() => {
      setImagesFunction = setImages
    }, [])
  
    return (
      <Slider className={styles.Card__slider} images={images}/>
    )
  }
 
  return (
    <>
      <Header/>
      {!(nets && netsProperties) ? <Loader/> :
        <section className={styles.Card}>
          <CardSlider getSetImagesFunction={(setState) => {setSetImagesFunction(setState)}}/>
          <div className={styles.Card__description}>
            <h1>Сетка садовая {netType == 'plastic' ? 'пластиковая' : 'безузелковая'} {cell} мм</h1>
            <CardProperties/>
            <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Molestias alias veniam labore, sapiente totam ipsum? Eum vero laborum adipisci unde, doloribus natus enim, voluptatibus alias facilis modi fuga laudantium nostrum, doloremque ipsa officiis similique fugiat. Doloremque sequi sit animi eaque asperiores? Hic iure sunt inventore harum error quod quasi dolore?</p>
          </div>
        </section>}
    </>
  )
}
Как вы видите я решил объявить CardSlider внутри Card, чтобы CardSlider имел доступ ко всем сущностям Card. Но сейчас я реализовал передачу setImages простым изменением переменной setImagesFunction. Я правда не раз пытался вместо setImagesFunction создать state (по типу: let [setImagesFunction , setSetImagesFunction] = useState()), а потом вместо обычного присвоения переменной (setImagesFunction = setImages) изменять state (по типу: setSetImagesFunction(setImages)). Но у меня всегда выходила ошибка: Cannot update a component (`CardSlider`) while rendering a different component (`Card`). Как я понял она связанна с тем, что я пытался изменить Card ещё до его рендера.
У меня в итоге то все работает, но чувство, что я написал кучку какашек меня никак не покидает.
Помогите пожалуйста понять правильным ли решением я воспользовался
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
05.04.2024, 21:41
Ответы с готовыми решениями:

Как передать из попап окна родителю переменную?
Привет знатокам JavaScript ! Что- то не получается передать переменную в родительское окно, делаю так в попапе: &lt;a...

Как передать родителю из iframe параметр средствами jQuery
Вызываю $('#run').contentWindow.location = 'run.php'; &lt;iframe id=&quot;run&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;display: none;&quot;...

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

37
Эксперт JSЭксперт HTML/CSS
 Аватар для krvsa
3857 / 1753 / 432
Регистрация: 14.03.2022
Сообщений: 4,439
11.04.2024, 15:00
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от samiroutka Посмотреть сообщение
вот тестовый пример
Молодец!
Ты уже сделал первый, осмысленный шаг к решению своей проблемы.
Сейчас сварганю некий вариант решения...

Добавлено через 14 минут
Цитата Сообщение от samiroutka Посмотреть сообщение
как изменять images, чтобы не было ререндера у компонентов CardProperty?
Например вот так...

Кликните здесь для просмотра всего текста
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import {useState, useEffect, memo} from 'react';
import ReactDOM from 'react-dom/client';
import './style.css';
 
// 
const CardProperty = memo(props => {
    console.log('Рендер CardProperty')
    return (
        <input/>
    )
 })
//
const CardSlider = ({images}) => {    
    return (
        <div>
            <p>Slider</p>
            <ul>
                {images.map(v => <li key={v}>{v}</li>)}
            </ul>
        </div>
    )
}
//
const Card = () => {
    const [images, setImages] = useState(['image1', 'image2'])
    console.log('Рендер Card')
    const act = _ => setImages(['image1', 'image2', 'image3'])
    return (
        <div>
            <CardSlider images={images}/>
            <div>
                {Array.from({length: 3}, (_, i) => <CardProperty key={i} />)}
            </div>
            <button onClick={act}>Add Image</button>
        </div>
    )
}
 
 
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <Card />
);

Я немного подделал твой пример под свое понимание стиля написания кода.
После изменения images ты не увидишь в консоли сообщений о рендере CardProperty.

Добавлено через 6 минут
Еще совет...
Такие вот "куски"
Цитата Сообщение от samiroutka Посмотреть сообщение
HTML5
1
2
3
4
5
<div>
        <CardProperty/>
        <CardProperty/>
        <CardProperty/>
</div>
Желательно оформлять отдельным компонентом...

Тогда меморизовать нужно будет только его, а не CardProperty.
И сам материнский компонент будет более компактен.
0
4 / 4 / 1
Регистрация: 26.03.2023
Сообщений: 153
11.04.2024, 15:32  [ТС]
Цитата Сообщение от krvsa Посмотреть сообщение
вариант решения
Твоё решение мне нравится, но ты сделать ещё кое-что чему я не придавал большого значения: ты объявлял компоненты отдельно, а я объявлял все компоненты в компоненте Card.
Я знаю, что так лучше не делать и я думаю, что сделаю рефакторинг (вроде это называется рефакторингом, а не декомпозицией, я путаю эти термины), но почему когда я объявляю компоненты внутри компонента Card и также как и ты использую мемоизацию, то у меня ничего не работает?
0
Эксперт JSЭксперт HTML/CSS
 Аватар для krvsa
3857 / 1753 / 432
Регистрация: 14.03.2022
Сообщений: 4,439
11.04.2024, 15:53
Цитата Сообщение от samiroutka Посмотреть сообщение
почему когда я объявляю компоненты внутри компонента Card и также как и ты использую мемоизацию, то у меня ничего не работает?
Ответ прост - ты каждый раз создаешь новые, пусть и меморизованные, компоненты.
0
4 / 4 / 1
Регистрация: 26.03.2023
Сообщений: 153
11.04.2024, 15:55  [ТС]
Почему я создаю новые компоненты?
0
Эксперт JSЭксперт HTML/CSS
 Аватар для krvsa
3857 / 1753 / 432
Регистрация: 14.03.2022
Сообщений: 4,439
11.04.2024, 16:17
Цитата Сообщение от samiroutka Посмотреть сообщение
Почему я создаю новые компоненты?
Что такое рендер компонента (в твоем случае Card)?
Как минимум - это вызов функции Card().
Что делается в этой функции - как минимум создаются (каждый раз) значения для переменных (в твоем случае CardProperty и пр.)
0
4 / 4 / 1
Регистрация: 26.03.2023
Сообщений: 153
11.04.2024, 16:20  [ТС]
Но рендер компонента Card происходит только один раз: при первом рендеринге Card, нет?
0
Эксперт JSЭксперт HTML/CSS
 Аватар для krvsa
3857 / 1753 / 432
Регистрация: 14.03.2022
Сообщений: 4,439
11.04.2024, 16:27
Цитата Сообщение от samiroutka Посмотреть сообщение
Но рендер компонента Card происходит только один раз
В моем примере выводится сообщение
Цитата Сообщение от krvsa Посмотреть сообщение
JavaScript
1
console.log('Рендер Card')
Всякий раз при рендере Card.
Первый раз когда страница создана...
И каждый раз - когда жмут на кнопку Add Image.


Вот сварганил тебе "альтернативный вариант", если прям так прет создавать компоненты внутри других компонентов...
Кликните здесь для просмотра всего текста
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import {useState, useEffect, memo, useCallback} from 'react';
import ReactDOM from 'react-dom/client';
import './style.css';
 
//
const CardSlider = ({images}) => {    
    return (
        <div>
            <p>Slider</p>
            <ul>
                {images.map(v => <li key={v}>{v}</li>)}
            </ul>
        </div>
    )
}
//
const Card = () => {
    const [images, setImages] = useState(['image1', 'image2'])
    console.log('Рендер Card')
    // 
    const CardProperty = useCallback(memo(props => {
        console.log('Рендер CardProperty')
        return (
            <input/>
        )
    }), [])
    const act = _ => setImages(['image1', 'image2', 'image3'])
    return (
        <div>
            <CardSlider images={images}/>
            <div>
                {Array.from({length: 3}, (_, i) => <CardProperty key={i} />)}
            </div>
            <button onClick={act}>Add Image</button>
        </div>
    )
}
 
 
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <Card />
);
0
4 / 4 / 1
Регистрация: 26.03.2023
Сообщений: 153
11.04.2024, 16:30  [ТС]
Я думал, что ререндер, это именно заново исполняется блок render (), но видимо при ререндере компонент начинает заново создавать всё переменные и сущности до блока render или я что-то снова не понял (
0
Эксперт JSЭксперт HTML/CSS
 Аватар для krvsa
3857 / 1753 / 432
Регистрация: 14.03.2022
Сообщений: 4,439
11.04.2024, 16:33
Что за "блок render ()"?

Добавлено через 1 минуту
samiroutka, рендер функционального компонента - это вызов функции, которой он был описан.

А далее все работает "как в обычной функции". Никакой разницы нет.
0
4 / 4 / 1
Регистрация: 26.03.2023
Сообщений: 153
11.04.2024, 16:33  [ТС]
Ой, не render, а return (уже крыша едет)
0
Эксперт JSЭксперт HTML/CSS
 Аватар для krvsa
3857 / 1753 / 432
Регистрация: 14.03.2022
Сообщений: 4,439
11.04.2024, 16:38
Цитата Сообщение от samiroutka Посмотреть сообщение
return
Так пока до return дойдет - будет выполняться каждая строка внутри функции...
0
4 / 4 / 1
Регистрация: 26.03.2023
Сообщений: 153
11.04.2024, 16:42  [ТС]
Да, я кажется понял. Тогда попробую переписать "нормально". Без вложенных компонентов, а то один раз попробовал вложить компонент в другой и почувствовал свободу от передачи кучи пропсов
0
Эксперт JSЭксперт HTML/CSS
 Аватар для krvsa
3857 / 1753 / 432
Регистрация: 14.03.2022
Сообщений: 4,439
11.04.2024, 17:00
Цитата Сообщение от samiroutka Посмотреть сообщение
почувствовал свободу от передачи кучи пропсов
Открой для себя контекст и стейт-менеджеры.
0
4 / 4 / 1
Регистрация: 26.03.2023
Сообщений: 153
11.04.2024, 17:08  [ТС]
Контексты я юзал, они не очень удобны. А стейт менеджеры не хочу юзать, чтобы react был чистый что ли. Хочу научиться на чистом реакте писать, думаю это будет полезно
0
Эксперт JSЭксперт HTML/CSS
 Аватар для krvsa
3857 / 1753 / 432
Регистрация: 14.03.2022
Сообщений: 4,439
11.04.2024, 17:20
Цитата Сообщение от samiroutka Посмотреть сообщение
Контексты я юзал, они не очень удобны
Ничем не хуже пропсов...
Стилистически даже интереснее.

Но дело хозяйские конечно...
0
250 / 184 / 58
Регистрация: 12.03.2021
Сообщений: 1,043
12.04.2024, 13:06
Цитата Сообщение от samiroutka Посмотреть сообщение
А стейт менеджеры не хочу юзать, чтобы react был чистый что ли
возможно, у нас разное представление и "чистоте", но всё ж глобальное хранилище выглядит чище, чем перекидывание пропсов через 100500 файлов
0
4 / 4 / 1
Регистрация: 26.03.2023
Сообщений: 153
12.04.2024, 13:16  [ТС]
Ты прав. Но я опять же не говорил что у меня на данный момент в проекте 100500 сущностей, но даже если они появятся, то думаю буду юзать дефолтный контекст
0
4 / 4 / 1
Регистрация: 26.03.2023
Сообщений: 153
13.04.2024, 09:24  [ТС]
Честно говоря не знаю как (к сожалению), но у меня теперь все работает и без memo. Я просто сделать декомпозицию (вывел все компоненты в отдельные файлы)
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
13.04.2024, 09:24

Дочерние процессы должны сгенерировать случайные числа и передать их родителю
помогите решить проблему: В общем есть 6 процессов, 1 родитель и 5 дочерних, дочернии процессы должны с генерировать случайные числа и...

Как правильно передать указатель на структуру, и правильно ее использовать
Я планирую сделать сортировку, но компилятор начал ругаться &quot;Нет существует подходящей функции преобразования &quot;Student&quot; в...

RestTemplate: как правильно правильно передать JSon
Мне дали ссылку на самодельный веб-сервис и список параметров, которые нужно передать. Общение идет через объекты JSon. Если...

Составить описание класса ребенок (Child), в котором задается имя ребенка, имена родителей, дата рождения ребенка
Добрый день. Очень нужна помощь по Объектно-ориентированному программированию! Вот собственно сама задача,: Составить описание класса...

Как работает setState()?
Доброго времени суток! Поясните, пожалуйста как работает метод setState() в данном коде. import React from &quot;react&quot;; ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
38
Ответ Создать тему
Новые блоги и статьи
сукцессия 25. Хронология ошибок
anaschu 12.07.2026
# От 50-тонного гриба до устойчивого леса: хроника ошибок при построении модели вековой сукцессии микоризы ## О чём эта статья В процессе построения ОДУ-модели (система дифференциальных. . .
сукцессия 24. Промежуточное общее описание модели
anaschu 12.07.2026
Хендофф: модель АМ→ЭКМ сукцессии микоризы (ризосфера, 50 лет) Содержание проекта Симуляция вековой (50 лет) экологической сукцессии в почве леса Основные участники: АМ-гриб, ЭКМ-гриб,. . .
сукцессия 23. Более физиологичная физиология, более экологичная экология, более диффурные диффуры.
anaschu 12.07.2026
Что реально нашли и починили за эти 5 часов Правило Линдемана (КПД конверсии сахара в тело, kEff) — раньше 100% полученного углерода шло прямо в биомассу гриба; теперь только kEff=0. 5 (после. . .
сукцессия 22. От артефактов к физиологии: калибровка агентной модели грибной сукцессии для воспроизведения сезонной динамики и pH-плато
anaschu 11.07.2026
Аннотация В данной работе представлена калибровка агентной модели динамики грибных сообществ (fungal-succession), направленная на устранение нефизичных артефактов (коллапс биомассы, мгновенное. . .
Сукцессия 20. Война автоботов. Делаем ставки. Лёд против "пш-пш!".
anaschu 11.07.2026
Битва ИИ в ризосфере: Как мы скрестили жесткие ОДУ, закон Фика и «подземный шантаж» Уважаемые коллеги! Хочу поделиться уникальным опытом ведения междисциплинарной компьютерной разработки. Прямо. . .
Сукцессия 19. Какие выводы я сделал из модели? Часть 2.Внутримикоризный стехиометрический буфер и хроно-дискретные зоны экспансии
anaschu 11.07.2026
Био-Инженерный Ликбез: Архитектура Модели Ризосферы Математический аппарат моделирования
Сукцессия 18. Какие выводы я сделал из войны грибов с деревьями? Часть 1- рассказ и немного про термины
anaschu 11.07.2026
Био-Инженерный Ликбез: Архитектура Модели Ризосферы Математический аппарат моделирования Система ОДУ описывает динамику изменения массы различных компонентов системы во времени. Ключевой. . .
Просветление в 5 секунд
kumehtar 10.07.2026
Андрей Веретенников выдал фразу недавно: "Вам не обязательно кем-то себя считать"
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru