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

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

07.07.2023, 19:28. Показов 554. Ответов 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
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
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
молодой
1769 / 1010 / 320
Регистрация: 17.07.2021
Сообщений: 2,048
Записей в блоге: 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
молодой
1769 / 1010 / 320
Регистрация: 17.07.2021
Сообщений: 2,048
Записей в блоге: 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
молодой
1769 / 1010 / 320
Регистрация: 17.07.2021
Сообщений: 2,048
Записей в блоге: 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
молодой
1769 / 1010 / 320
Регистрация: 17.07.2021
Сообщений: 2,048
Записей в блоге: 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
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
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
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru