Используя Gatsby, у меня есть пользовательский компонент InvertedSection
, который меняет класс элемента HTML при прокрутке раздела, позволяя мне изменить стиль заголовка. То есть, когда верхняя часть элемента с перевернутой секцией достигает верхней части окна, и пока нижняя часть элемента с перевернутой секцией не достигает верхней части окна, заголовок является прозрачным. Я выполняю sh, используя состояние Redux.
В моем компоненте invertedSection.js
я переключаю состояние локально - чтобы ограничить вызовы Redux только при локальном изменении состояния - а также используя Redux createStore.js
. Затем в layout.js
я использую состояние Redux для установки HTML className с использованием React шлем .
Моя проблема двоякая:
- при навигации со страницы, использующей компонент
InvertedSection
, до страницы, которая не использует этот компонент, состояние Redux invertedHeader
устанавливается равным true
и - , если у меня несколько разделов
InvertedSection
на одном страница, изменение состояния работает только для первого раздела, а не для любых последующих перевернутых разделов.
I думаю проблема с (1) выше заключается в том, что страница прокручивается вверх где находится InvertedSection
, прежде чем перейти на новую страницу, таким образом, invertedHeader
будет true
при загрузке новой страницы. Но я не могу найти, как заставить редукс сбрасывать это состояние при каждом изменении маршрута.
Мысли? Все работает, если я перехожу на / со страниц, которые обе содержат InvertedSection
, поэтому, возможно, мне нужно вызывать обработчик прокрутки на каждой странице? ИЛИ хотя бы вызвать проверку положения прокрутки и изменение состояния? Redux для меня немного новый, так что это может немного сбивать с толку.
Спасибо!
# Component
# /components/invertedSection.js
import React, { useState, useEffect } from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
const InvertedSection = ({ invertHeader, revertHeader, className, children }) => {
let targetSection = React.createRef()
const [isViz, setIsViz] = useState(false)
useEffect(() => {
handleScroll()
window.addEventListener('scroll', handleScroll, true)
return () => {
window.removeEventListener('scroll', handleScroll, true)
}
})
const handleScroll = () => {
if (targetSection.current) {
const rect = targetSection.current.getBoundingClientRect()
if (rect && rect.top <= 0 && rect.bottom >= 0) {
if (!isViz) {
setIsViz(true)
invertHeader()
console.log('header invert')
}
} else {
if (isViz) {
setIsViz(false)
revertHeader()
console.log('header revert')
}
}
}
}
return (
<section ref={targetSection} className={className}>
{children}
</section>
)
}
InvertedSection.propTypes = {
invertHeader: PropTypes.func.isRequired,
revertHeader: PropTypes.func.isRequired,
}
const mapStateToProps = ({ invertedHeader }) => {
return { invertedHeader }
}
const mapDispatchToProps = dispatch => {
return {
invertHeader: () => dispatch({ type: `INVERTHEADER` }),
revertHeader: () => dispatch({ type: `REVERTHEADER` }),
}
}
export default connect(mapStateToProps, mapDispatchToProps)(InvertedSection)
# Redux
# /state/createStore.js
import { createStore as reduxCreateStore } from 'redux'
const reducer = (state, action) => {
switch (action.type){
case `INVERTHEADER`:
return Object.assign({}, state, {
invertedHeader: true,
})
case `REVERTHEADER`:
return Object.assign({}, state, {
invertedHeader: false,
})
default:
break
}
return state
}
const initialState = {
invertedHeader: false,
}
const createStore = () => reduxCreateStore(reducer, initialState)
export default createStore
# Layout
# /components/layout.js
import React, { useEffect } from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { useStaticQuery, graphql } from 'gatsby'
import { ThemeProvider } from 'styled-components'
import theme from '../styles/theme'
import Helmet from 'react-helmet'
import GlobalStyle from '../styles/global'
import SiteHeader from './siteHeader/siteHeader'
import SiteFooter from './sitefooter/siteFooter'
const Layout = ({ children, invertedHeader }) => {
const data = useStaticQuery(graphql`
query {
site {
...siteMeta
}
}
`)
return (
<ThemeProvider theme={theme}>
<Helmet>
<html className={`${invertedHeader ? 'inverted-header' : ''}`} />
</Helmet>
<GlobalStyle />
<SiteHeader
siteTitle={data.site.siteMetadata.title}
/>
{children}
<SiteFooter />
</ThemeProvider>
)
}
Layout.propTypes = {
children: PropTypes.node.isRequired,
invertedHeader: PropTypes.bool.isRequired,
}
const mapStateToProps = ({ showNav, invertedHeader }) => {
return { showNav, invertedHeader }
}
export default connect(mapStateToProps)(Layout)
# Index
# /pages/index.js
import React from 'react'
import Layout from '../components/layout'
import InvertedSection from '../components/section'
export default ({ data }) => {
return (
<Layout>
<InvertedSection>
This section uses an inverted header state
</InvertedSection>
<section>
This section uses normal header state
</section>
</Layout>
)
}