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

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

05.04.2024, 21:41. Показов 2641. Ответов 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
3864 / 1769 / 434
Регистрация: 14.03.2022
Сообщений: 4,460
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
3864 / 1769 / 434
Регистрация: 14.03.2022
Сообщений: 4,460
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
3864 / 1769 / 434
Регистрация: 14.03.2022
Сообщений: 4,460
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
3864 / 1769 / 434
Регистрация: 14.03.2022
Сообщений: 4,460
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
3864 / 1769 / 434
Регистрация: 14.03.2022
Сообщений: 4,460
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
3864 / 1769 / 434
Регистрация: 14.03.2022
Сообщений: 4,460
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
3864 / 1769 / 434
Регистрация: 14.03.2022
Сообщений: 4,460
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
3864 / 1769 / 434
Регистрация: 14.03.2022
Сообщений: 4,460
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
Ответ Создать тему
Новые блоги и статьи
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU. Опрашиваются регистры. . .
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
мат медиц модель 30. презентация проекта
anaschu 27.08.2026
хоп хоп хоп хидахоп, а я кладую))
Как у меня протекала болезнь
zorxor 27.08.2026
Здравствуйте, друзья! Эта запись блога предназначена именно для вас - для моих дорогих друзей, которые знали меня лично. Чтобы ответить на вопрос - а что же со мной произошло на самом деле? Я учился. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru