@cedFlame

Как решить проблему скролла в react?

Вообщем у меня было странная задумка. Я делаю сайт, механика такова, что пользователь заходит на сайт, может скролить вниз и вверх, при клике на какую нибудь вкладку в навбаре удалются все дом элементы и создаются два новых страница на которой находится пользователь и страница на которую он должен попасть. Попадает он на неё при помощи gsap горизонтального скролла и при помощи библиотеки react-scroll. Вообще реализация работает, но есть помеха, она заключается в том что пока реализуется handleClick() пользователь не может кликать, скролить, нажимать какие либо клавиши на сайте, иначе анимация скроло просто прекращается и просто появляется страница на которую кликнул пользователь в навбаре. Реализация странная, тк я в реакт и в js всего полтора месяца. Хотел бы обратиться за помощью как правильно реализовать мой кривой код?
Вот и он:
App:
import './App.css';
import {Header} from "./components/header/Header";
import {Main} from "./components/main/Main";
import gsap from "gsap";
import ScrollTrigger from "gsap/ScrollTrigger";
import React, {useLayoutEffect, useRef, useState} from "react";
import './styles.css'

gsap.registerPlugin(ScrollTrigger);

function App() {

    const [data, setData]
        = useState({state: false,
        panel: {object: <Main/>, colors: ['#4d4d4d','#fff','#4d4d4d','#4d4d4d','#4d4d4d']},
        panelBefore: {object: <Main/>, colors: ['#4d4d4d','#fff','#4d4d4d','#4d4d4d','#4d4d4d']},
        navBarPos: 'absolute'})
    const handleData = (state, panel, panelBefore, navBarPos) => {
        setData({state: state, panel: panel, panelBefore: panelBefore, navBarPos: navBarPos})
    }
    const component = useRef();
    const slider = useRef();

    useLayoutEffect(() => {
        let ctx = gsap.context(() => {
            let panels = gsap.utils.toArray(".panel");
            gsap.to(panels, {
                xPercent: -100 * (panels.length),
                ease: "none",
                scrollTrigger: {
                    trigger: slider.current,
                    pin: true,
                    scrub: 0,
                    snap: 0 / (panels.length - 1),
                    end: () => "+=" + slider.current.offsetWidth
                }
            });
        }, component);
        return () => ctx.revert();
    })

    return (
        <>
                <div key={'a'} ><Header handleData={handleData} color={data.panel.colors} state={data.state} position={data.navBarPos}/></div>
                {
                    !data.state ?
                        (<>
                                <div key={'b'} style={{display: 'none'}} ref={component}>
                                    <div key={'c'} ref={slider}></div>
                                </div>
                                {data.panel.object}
                            </>
                        )
                        :
                        (<div key={'d'} ref={component}>
                            <div key={'e'} ref={slider} className="container">
                                <div key={'f'} className="panel">{data.panelBefore.object}</div>
                                <div key={'g'} className="panel">{data.panel.object}/></div>
                            </div>
                        </div>)
                }
        </>
    );
}
export default App;

Header:
import React from "react";
import {NavBar} from './NavBar'
import styled from 'styled-components';

export const Header = (props) => {
    const handleData = props.handleData
    const position = props.position
    const color = props.color

    return (
        <>
            <Wrapper position={position} >
                <Label>

                </Label>
                <NavBarStyles>
                    <NavBar handleData={handleData} color={color} />
                </NavBarStyles>
                <SocialMedia>

                </SocialMedia>
            </Wrapper>
        </>
    );
}

NavBar:
import React from "react";
import {motion} from "framer-motion";
import {useState} from "react";
import {Main} from "../main/Main";
import {Services} from "../services/Services";
import {Contacts} from "../contacts/Contacts";
import {Works} from "../works/Works";
import {About} from "../about/About";
import $ from "jquery";
import styled from "styled-components";

let handleData


export const NavBar = (props) => {

    handleData = props.handleData
    const [selected, setSelected] = useState(false)
    const [getPanel, setPanel] = useState( {object: <Main/>, colors: ['#4d4d4d','#fff','#4d4d4d','#4d4d4d','#4d4d4d']})
    const [activeIndex, setActive] = useState(0)

    const Scroll = require('react-scroll');
    const scroll = Scroll.animateScroll;

    const menuData = [{
        name: 'главная', scroll: function () {
            scroll.scrollTo(window.innerWidth)
        },
        panel: {object: <Main/>, colors: ['#4d4d4d','#e8e6e6','#4d4d4d','#4d4d4d','#4d4d4d']},
        color: props.color[0],
        number: 0
    },
        {
            name: 'обо мне', scroll: function () {
                scroll.scrollTo(window.innerWidth)
            },
            panel: {object: <About/>, colors: ['#4d4d4d','#4d4d4d','#4d4d4d','#4d4d4d','#4d4d4d']},
            color: props.color[1],
            number: 1
        },
        {
            name: 'мои работы', scroll: function () {
                scroll.scrollTo(window.innerWidth)
            },
            panel: {object: <Works/>, colors: ['#4d4d4d','#4d4d4d','#4d4d4d','#4d4d4d','#4d4d4d']},
            color: props.color[2],
            number: 2
        },
        {
            name: 'услуги', scroll: function () {
                scroll.scrollTo(window.innerWidth)
            },
            panel: {object: <Services/>, colors: ['#4d4d4d','#4d4d4d','#4d4d4d','#4d4d4d','#4d4d4d']},
            color: props.color[3],
            number: 3
        },
        {
            name: 'контакты', scroll: function () {
                scroll.scrollTo(window.innerWidth)
            },
            panel: {object: <Contacts/>, colors: ['#4d4d4d','#4d4d4d','#4d4d4d','#4d4d4d','#4d4d4d']},
            color: props.color[4],
            number: 4
        }]

    const handleClick = (item, index) => {
        setActive(index)
        handleData(true, item.panel, getPanel, 'fixed')
        $('html').css('overflow-y', 'hidden')
        item.scroll()
        setSelected(true)
        setTimeout(function () {
            setPanel(item.panel)
        }, 1100)
        setTimeout(function () {
            window.scrollTo(0, 0)
        }, 1200)
        setTimeout(function () {
            handleData(false, item.panel, getPanel, 'absolute')
            $('html').css('overflow-y', 'visible')
            $('window').css('height', '100vh')
            setSelected(false)
        }, 1200)
    }

    return (
        <>
            <Wrapper>
                {
                    menuData.map((item, index) => (
                        <MenuItem
                            key={'a'}
                            item={item}
                            isSelected={activeIndex === index}
                            handleClick={() => selected === false && handleClick(item, index)}
                            selected={selected}
                        />
                    ))
                }
            </Wrapper>
        </>
    );
}

const MenuItem = (props) => {
    const {
        item,
        isSelected,
        handleClick,
        selected
    } = props;

    return (
        <motion.div
            onClick = {handleClick}
        >
            {isSelected && <ActiveLine item={item} color={item.color}/>}
            <Item color={item.color} pointerEvents={selected ? 'none':'auto'}>
                {item.name}
            </Item>
        </motion.div>
    );

}

const ActiveLine = (props) => {

    const color = props.color

    return (
        <>
            <motion.div
                layoutId='size'
                transition={{
                    duration: 1
                }}
            >
                <Line color={color} />
            </motion.div>
        </>
    );
}

styles.css:
.container {
    width: 200vw;
    height: 100vh;
    display: flex;
    flex-wrap: wrap;
}

.firstContainer {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    height: 100vh;
    background: yellow;
}

.lastContainer {
    display: flex;
    height: 100vh;
    background: yellow;
}

.panel {
    width: 100vw;
    height: 100vh;
}


Все компоненты которые я не скинул и присутствующие в коде не имеют логики, имеют только стили.
  • Вопрос задан
  • 178 просмотров
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы