С Новым годом! Форум программистов, компьютерный форум, киберфорум
JavaScript: ReactJS
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/3: Рейтинг темы: голосов - 3, средняя оценка - 4.67
4 / 4 / 1
Регистрация: 26.03.2023
Сообщений: 153
1

Почему state работает не так как я ожидал?

07.07.2023, 19:28. Показов 566. Ответов 7

Author24 — интернет-сервис помощи студентам
Вот мой observer
Javascript
1
2
3
4
5
6
  let observer = new IntersectionObserver(entries => {
    if (entries[0].isIntersecting){
      setCurrentPage(currentPage + 1)
      console.log(currentPage)
    }
  }, {})
Я хочу чтобы при вызове observer, currentPage менялось на 1, но почему-то это происходит только один раз. При последующих отрабатываниях, currentPage не увеличивается больше 2. Знаю что можно использовать функцию в setCurrentPage, но тогда актуальное значение переменной видно только в функции setCurrentPage, а мне нужно чтобы актуальное значение currentPage было доступно на всех уровнях. Помогите мне пожалуйста, не могу понять как это решить
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
07.07.2023, 19:28
Ответы с готовыми решениями:

Почему фильтрация работает не так как ожидал в таблице .rdl отчета?
Здравствуйте! Датасет, определенный в моем .rdl отчете возвращает таблицу, в которой есть...

Почему не работает так как надо
#include <vcl.h> #pragma hdrstop #include "Unit1.h"...

Почему работает не так как надо?
В общем вот в чем вопрос, есть код на СИ. Задача такова ввести с клавы день, месяц, год рождения...

Почему не работает так, как надо?
uses Math; function Sum(n:integer): extended; begin if n=0 then sum:=0 else sum:=power(n,...

Почему malloc работает не так, как ожидается?
int main() { int* p =malloc(sizeof(int)); p=5; printf("%s\n",strerror(errno)); ...

7
молодой
1774 / 1019 / 320
Регистрация: 17.07.2021
Сообщений: 2,066
Записей в блоге: 12
07.07.2023, 23:02 2
попробуйте так

Javascript
1
setCurrentPage(currentPage  => currentPage + 1)
и этот код

Javascript
1
console.log(currentPage),
покажет изменение только со следующей отрисовкой

Но лучше покажите весь код компонента, мне кажется будут еще рекомендации
0
4 / 4 / 1
Регистрация: 26.03.2023
Сообщений: 153
08.07.2023, 10:07  [ТС] 3
Вот весь компонент
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import React, {useState, useEffect, useRef} from 'react'
import styles from './Posts.module.css'
import {getAmountOfPages, getServerData} from '../../components/utils.js'
import {allDataContext} from '../../components/contexts.js'
// ----------
import Post_form from '../../components/Post_form/Post_form.jsx'
import Post_filter from '../../components/Post_filter/Post_filter.jsx'
import Post_search from '../../components/Post_search/Post_search.jsx'
import Post_list from '../../components/Post_list/Post_list.jsx'
import Submit_button from '../../components/UI/Submit_button/Submit_button'
import Post_counter from '../../components/Post_counter/Post_counter'
import Loader from '../../components/UI/Loader/Loader.jsx'
import Pagination from '../../components/UI/Pagination/Pagination.jsx'
 
 
// ------------------------------
function Posts() {
 
  let [data, setData] = useState('')
  let [searchData, setSearchData] = useState('')
 
  let [hiddenState, setHiddenState] = useState(true)
  let [loading, setLoading] = useState(false)
  let isEternalPosts = true
 
  let mainLimit = 10
  let amountOfButtons = getAmountOfPages(100, mainLimit)
  let [currentPage, setCurrentPage] = useState(1)
 
  let setServerData = async (page) => {
    setLoading(true)
    setData(await getServerData(mainLimit, page))
    setLoading(false)
  }
 
  useEffect(() => {
    setServerData()
  }, [])
 
  let observerPoint = useRef()
 
  let observer = new IntersectionObserver(entries => {
    if (entries[0].isIntersecting){
      setCurrentPage(currentPage  => currentPage + 1)
      console.log(currentPage)
    }
  }, {})
 
  useEffect(() => {
    observer.observe(observerPoint.current)
  }, [data])
 
  // --------------------
  return (
    <allDataContext.Provider value={{data, setData, searchData, setSearchData}}>
      <div className="App">
        <Submit_button onClick={() => setHiddenState(false)} style={{marginTop: '2%'}}>Добавить пост</Submit_button>
        <Post_form hidden={hiddenState} setHiddenState={setHiddenState}/>
 
        <br/>
        <hr/>
 
        <h1 className={styles.title}>Посты</h1>
        <div className={styles.box}>
          <Post_search/>
          <Post_filter options={[
            {name: 'По названию', value: 'title',},
            {name: 'По описанию', value: 'description',},
          ]}/>
          <Post_counter>{data.length}</Post_counter>
        </div>
 
        {loading
        ? 
          <Loader/>
        : 
          <>
            <Post_list ref={observerPoint}/>
          </>
        }
        {isEternalPosts
        ?
          <></>
        :
          <Pagination amountOfButtons={amountOfButtons} currentPage={currentPage} setCurrentPage={setCurrentPage} setServerData={setServerData} limit={mainLimit}/>
        }
      </div>
    </allDataContext.Provider>
  )
}
 
export default Posts
Используя функцию таким образом
Javascript
1
setCurrentPage(currentPage  => currentPage + 1)
ничего не поменялось

-----------------------------------------

Я ещё пробовал сделать так:
Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  let actualCurrentPage = 0
 
  useEffect(() => {
    console.log(actualCurrentPage)
  }, [actualCurrentPage])
 
  let observer = new IntersectionObserver(entries => {
    if (entries[0].isIntersecting){
      setCurrentPage(actualValue  => {
        actualCurrentPage = actualValue + 1
        return actualValue + 1
      })
    }
  }, {})
но почему-то useEffect вообще не реагирует на изменение переменной
0
молодой
1774 / 1019 / 320
Регистрация: 17.07.2021
Сообщений: 2,066
Записей в блоге: 12
08.07.2023, 13:30 4
Немного накодил, смысл в том что нужно следить за тем чтобы ты работал с одним и тем же обсервером, который не будет пересоздаваться каждую перерисовку

intersectionobserver example

App.tsx
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
import "./styles.css";
import React from "react";
import useIntersectionObs from "./useIntersectionObs";
 
export default function App() {
  const main = React.useRef<HTMLDivElement>();
  const target = React.useRef<HTMLDivElement>();
  const { addTarget, isIntersect, setRoot } = useIntersectionObs();
  const [counter, setCounter] = React.useState(0);
  React.useEffect(() => {
    if (isIntersect) {
      setCounter((prev) => prev + 1);
    }
  }, [isIntersect]);
  return (
    <>
      <div
        id="main"
        ref={(element) => {
          if (element && !main.current) {
            setRoot(element);
            main.current = element;
          }
        }}
      >
        <p>scroll to see the target</p>
        <div className="buffer"></div>
        <div
          id="target"
          ref={(element) => {
            if (element && !target.current) {
              addTarget(element);
              target.current = element;
            }
          }}
        ></div>
        <div className="buffer"></div>
      </div>
      <div id="output">counter: {counter}</div>
    </>
  );
}
useIntersectionObs.tsx
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
44
45
46
47
48
49
50
51
52
53
54
import React from "react";
const io_options = {
  root: null,
  rootMargin: "0px",
  threshold: 0.5
};
 
const useIntersectionObs = () => {
  const [isIntersect, setIntersect] = React.useState(false);
  const [root, setRootElement] = React.useState<Element | null>(null);
  // элементы которые мы хотим добавить в обсервер, но обсервер еще не готов их принять
  const elements = React.useRef<Element[]>([]);
  // Для исключения повторной инициализации
  const ioRef = React.useRef<IntersectionObserver>();
  const io_callback = React.useCallback(
    (entries: IntersectionObserverEntry[]) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
          setIntersect(true);
        } else {
          setIntersect(false);
        }
      });
    },
    []
  );
  const io_observer = React.useMemo(() => {
    if (root === null || ioRef.current) return ioRef.current;
    const io = new IntersectionObserver(io_callback, io_options);
    ioRef.current = io;
    for (const element of elements.current) {
      io.observe(element);
    }
    elements.current = [];
    return io;
  }, [io_callback, root]);
  const addTarget = React.useCallback(
    (target: Element) => {
      if (io_observer) {
        io_observer?.observe(target);
      } else {
        elements.current.push(target);
      }
    },
    [io_observer]
  );
  const setRoot = React.useCallback((element: Element) => {
    if (element instanceof Element === false) return;
    setRootElement((prevElement) => (!prevElement ? element : prevElement));
  }, []);
  return { addTarget, isIntersect, setRoot };
};
 
export default useIntersectionObs;
0
4 / 4 / 1
Регистрация: 26.03.2023
Сообщений: 153
08.07.2023, 15:45  [ТС] 5
Мне кажется можно более лаконично и с меньшим количеством кода решить эту проблему

Добавлено через 33 минуты
Я сейчас сидела, и хоть какое-то корявое решение у меня получилось после того, как я импортировал 'react-intersection-observer'. Вот код:
Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
let {ref, inView} = useInView({})  
 
  useEffect(() => {
    if (inView && isEternalPosts && currentPage < 11){     
      if (currentPage == 1){
        setCurrentPage(currentPage+2)
        updateData(currentPage+1)
      } else {
        setCurrentPage(currentPage+1)
        updateData(currentPage)
      }
    }
  }, [inView])
Если знаете, как сделать ещё проще, то пожалуйста напишите

Весь компонент:
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import React, {useState, useEffect, useRef, useLayoutEffect} from 'react'
import { useInView } from 'react-intersection-observer'
import styles from './Posts.module.css'
import {getAmountOfPages, getServerData} from '../../components/utils.js'
import {allDataContext} from '../../components/contexts.js'
// ----------
import Post_form from '../../components/Post_form/Post_form.jsx'
import Post_filter from '../../components/Post_filter/Post_filter.jsx'
import Post_search from '../../components/Post_search/Post_search.jsx'
import Post_list from '../../components/Post_list/Post_list.jsx'
import Submit_button from '../../components/UI/Submit_button/Submit_button'
import Post_counter from '../../components/Post_counter/Post_counter'
import Loader from '../../components/UI/Loader/Loader.jsx'
import Pagination from '../../components/UI/Pagination/Pagination.jsx'
 
 
// ------------------------------
function Posts() {
 
  let [data, setData] = useState('')
  let [searchData, setSearchData] = useState('')
 
  let [hiddenState, setHiddenState] = useState(true)
  let [loading, setLoading] = useState(false)
  let isEternalPosts = false
 
  let mainLimit = 10
  let amountOfButtons = getAmountOfPages(100, mainLimit)
  let [currentPage, setCurrentPage] = useState(1)
  let actualPage = 1
 
  let setServerData = async (page) => {
    setLoading(true)
    setData(await getServerData(mainLimit, page))
    setLoading(false)
  }
 
  let updateData = async (page) => {
    setData([...data, ...await getServerData(mainLimit, page)])
  }
 
  useEffect(() => {
    setServerData()
  }, [])
 
  let {ref, inView} = useInView({})  
 
  useEffect(() => {
    if (inView && isEternalPosts && currentPage < 11){     
      if (currentPage == 1){
        setCurrentPage(currentPage+2)
        updateData(currentPage+1)
      } else {
        setCurrentPage(currentPage+1)
        updateData(currentPage)
      }
    }
  }, [inView])
 
  // --------------------
  return (
    <allDataContext.Provider value={{data, setData, searchData, setSearchData}}>
      <div className="App">
        <Submit_button onClick={() => setHiddenState(false)} style={{marginTop: '2%'}}>Добавить пост</Submit_button>
        <Post_form hidden={hiddenState} setHiddenState={setHiddenState}/>
 
        <br/>
        <hr/>
 
        <h1 className={styles.title}>Посты</h1>
        <div className={styles.box}>
          <Post_search/>
          <Post_filter options={[
            {name: 'По названию', value: 'title',},
            {name: 'По описанию', value: 'description',},
          ]}/>
          <Post_counter>{data.length}</Post_counter>
        </div>
 
        {loading
        ? 
          <Loader/>
        : 
          <>
            <Post_list/>
            <div style={{width: '100%', height: '10px'}} ref={ref}></div>
          </>
        }
        {isEternalPosts
        ?
          <></>
        :
          <Pagination amountOfButtons={amountOfButtons} currentPage={currentPage} setCurrentPage={setCurrentPage} setServerData={setServerData} limit={mainLimit}/>
        }
      </div>
    </allDataContext.Provider>
  )
}
 
export default Posts
1
молодой
1774 / 1019 / 320
Регистрация: 17.07.2021
Сообщений: 2,066
Записей в блоге: 12
08.07.2023, 15:46 6
с одной стороны лаконично с точки зрения написания кода, с другой в бандл добавится весь код библиотеки "react-intersection-observer" хотя это может быть и не критично для Вашего проекта. Главное чтобы Вас все устраивало
0
4 / 4 / 1
Регистрация: 26.03.2023
Сообщений: 153
08.07.2023, 17:56  [ТС] 7
???

Добавлено через 2 часа 3 минуты
Я просто не понимаю как работает useState, с библиотекой react-intersection state обновляется быстро, а без библиотеке state обновляется только после рендеринга. Не понимаю как это работает
0
молодой
1774 / 1019 / 320
Регистрация: 17.07.2021
Сообщений: 2,066
Записей в блоге: 12
08.07.2023, 21:33 8
Цитата Сообщение от samiroutka Посмотреть сообщение
Я просто не понимаю как работает useState, с библиотекой react-intersection state обновляется быстро, а без библиотеке state обновляется только после рендеринга. Не понимаю как это работает
библиотека react-intersection state под капотом также использует хуки react, в том числе и useState. В вашем первоначальном коде была как минимум одна проблема, это то что обсервер пересоздавался каждую перерисовку компонента, а добавление элемента который отслеживался выполняось только когда менялась дата,

Javascript
1
2
3
  useEffect(() => {
    observer.observe(observerPoint.current)
  }, [data])
и как следствие в какой то момент обсервер продолжал перезодаваться, а отслеживаемый элемент в новый экземпляр обсервера не добавлялся и счетчик пересечений не увеливался потому что обсерверу нечего было отслеживать , поэтому я Вам посоветовал использовать экземпляр обсервера который не пересоздается.

Любое изменение стейта или пропсов приводит к перерисовке компонента, для того чтобы хранить данные между перерисовками илспользуется мемоизация useMemo useCallback и рефы. Читайте про них в документации.
0
08.07.2023, 21:33
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
08.07.2023, 21:33
Помогаю со студенческими работами здесь

Почему код работает не так как нужно?
Проблемное место выделил подчеркиваниями сверху и снизу. Так же добавил код парсера, хотя вроде...

Почему Remove работает не так, как предполагалось
Доброго времени суток! Извините, если тема оформлена не правильно, я новичок на cyberforum....

Почему цикл работает не так, как ожидается?
Двумя способами реализовал цикл, который увеличивает годовую зарплату на 10% при нажатии 'y' до тех...

Почему программа со структурой не работает так как надо
Вот код программы: #include &lt;iostream &gt; &lt;iostream&gt; #include &lt;cstdlib&gt;&lt;cstdlib&gt; #include...

Почему макрос так медленно работает? Как ускорить?
6000 строк сделал примерно за 5 минут почему макрос так долго всё делает? как ускорить? Sub...

Как правильно обновлять state на основе предыдущего значения state? Какие могут при этом возникнуть проблемы?
Как правильно обновлять state на основе предыдущего значения state? Какие могут при этом возникнуть...


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

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Новые блоги и статьи
Книги и учебные ресурсы по C#
InfoMaster 08.01.2025
Базовые учебники и руководства Одной из лучших книг для начинающих является "C# 10 и . NET 6 для начинающих" Эндрю Троелсена и Филиппа Джепикса . Книга последовательно раскрывает основные концепции. . .
Что такое NullReferenceEx­­­ception и как исправить?
InfoMaster 08.01.2025
NullReferenceException - одно из самых распространенных исключений, с которым сталкиваются разработчики на C#. Это исключение возникает при попытке обратиться к членам объекта (методам, свойствам или. . .
Что такое Null Pointer Exception (NPE) и как это исправить?
InfoMaster 08.01.2025
Null Pointer Exception (NPE) - это одно из самых распространенных исключений в Java, которое возникает при попытке использовать ссылку на объект, значение которой равно null. Это исключение относится. . .
Русский язык в консоли C++
InfoMaster 08.01.2025
При разработке программ на C++ одной из частых проблем, с которой сталкиваются русскоязычные программисты, является корректное отображение кириллицы в консольных приложениях. Эта проблема особенно. . .
Telegram бот на C#
InfoMaster 08.01.2025
Разработка ботов для Telegram стала неотъемлемой частью современной экосистемы мессенджеров. C# предоставляет мощный и удобный инструментарий для создания разнообразных ботов, от простых. . .
Использование GraphQL в Go (Golang)
InfoMaster 08.01.2025
Go (Golang) является одним из наиболее популярных языков программирования, используемых для создания высокопроизводительных серверных приложений. Его архитектурные особенности и встроенные. . .
Что лучше использовать при создании класса в Java: сеттеры или конструктор?
Alexander-7 08.01.2025
Вопрос подробнее: На вопрос: «Когда одновременно создаются конструктор и сеттеры в классе – это нормально?» куратор уточнил: «Ваш класс может вообще не иметь сеттеров, а только конструктор и геттеры. . .
Как работать с GraphQL на TypeScript
InfoMaster 08.01.2025
Введение в GraphQL и TypeScript В современной разработке веб-приложений GraphQL стал мощным инструментом для создания гибких и эффективных API. В сочетании с TypeScript, эта технология. . .
Счётчик на базе сумматоров + регистров и генератора сигналов согласования.
Hrethgir 07.01.2025
Создан с целью проверки скорости асинхронной логики: ранее описанного сумматора и предополагаемых fast регистров. Регистры созданы на базе ранее описанного, предполагаемого fast триггера. То-есть. . .
Как перейти с Options API на Composition API в Vue.js
BasicMan 06.01.2025
Почему переход на Composition API актуален В мире современной веб-разработки фреймворк Vue. js продолжает эволюционировать, предлагая разработчикам все более совершенные инструменты для создания. . .
Архитектура современных процессоров
inter-admin 06.01.2025
Процессор (центральный процессор, ЦП) является основным вычислительным устройством компьютера, которое выполняет обработку данных и управляет работой всех остальных компонентов системы. Архитектура. . .
История создания реляционной модели баз данных, правила Кодда
Programming 06.01.2025
Предпосылки создания реляционной модели В конце 1960-х годов компьютерная индустрия столкнулась с серьезными проблемами в области управления данными. Существовавшие на тот момент модели данных -. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru