Я столкнулся с препятствием при составлении описанного ниже процесса. Я пытаюсь создать контекст, который будет глобально предоставлять свойства окна компонентам, чтобы компоненты могли реагировать на изменения окна (прокрутка, изменение размера и т. Д. c).
Я делаю это для того, чтобы чем каждый компонент, выполняющий свой собственный набор прослушивателей событий. Мне нужно запустить только один набор и передать результаты вниз.
Пока что контекст добавляет слушателей прокрутки и изменения размера, регулирует их и делает значения доступными для оболочки поставщика. Все работает нормально, и значения доступны в обернутом компоненте.
//WindowContext.js
import React, { Component, createContext } from "react"
import throttle from "lodash.throttle"
export const WindowContext = createContext()
class WindowContextProvider extends Component {
constructor(props) {
super(props)
this.state = {
windowScrollY: null,
windowInnerHeight: null,
}
this.throttledFunction = throttle(this.updateState, 500)
}
componentDidMount() {
window.addEventListener("scroll", this.throttledFunction, false)
window.addEventListener("resize", this.throttledFunction, false)
}
componentWillUnmount() {
window.removeEventListener("scroll", this.throttledFunction, false)
window.removeEventListener("resize", this.throttledFunction, false)
}
updateState = () => {
this.setState({
windowScrollY: window.scrollY,
windowInnerHeight: window.innerHeight,
})
}
render() {
return (
<WindowContext.Provider value={{ ...this.state }}>
{this.props.children}
</WindowContext.Provider>
)
}
}
export default WindowContextProvider
Проблема
В SomeComponent.js
ниже вы можете увидеть, что это это то, что я пытаюсь сделать. У него две фундаментальные проблемы. Я не могу (не должен) устанавливать состояние в рендере, поэтому я не уверен, как я могу установить isActive
в состоянии в значение true (чтобы какой-то тернарный оператор мог его использовать). И координаты элемента, которые я собираю в componentDidMount, - это stati c, что означает, что я не могу сопоставить их с прокруткой или внутренней высотой, чтобы определить, отображается ли элемент.
//SomeComponent.js
import React from "react"
import ReactDOM from "react-dom"
import { WindowContext } from "../contexts/WindowContext"
class DevTools extends React.Component {
constructor(props) {
super(props)
this.state = {
isActive: false, //want to set isActive:true if
element: null,
}
}
componentDidMount = () => {
this.setState({
element: ReactDOM.findDOMNode(this).getBoundingClientRect(),
})
}
render() {
return (
<WindowContext.Consumer>
{context => {
//THE CRUX OF THE PROBLEM
const { windowScrollY, windowInnerHeight } = context
console.log(windowScrollY) //tracked
console.log(windowInnerHeight) //tracked
console.log(this.state.element) //not tracked
//this.state.element is currently static as it is simply set on mount, needs to be tracked
//adding an event listener would defeat the point of creating the context
//Below not an option, cannot set state within render, not sure how else to manage toggling when the element is visible
handleWindowChange = () => {
if (this.state.element.top + 100 < windowInnerHeight && this.state.element.bottom >= 0) {
this.setState({
isActive: true,
})
}
}
return (
//some div with a ternary operator
Я пытаюсь придумать решение, которое отслеживает прослушиватели событий (прокрутка, изменение размера), но также отслеживает положение любого компонента, который оборачивается поставщиком. и вместо этого обработайте соответствие их видимости. Но я изо всех сил пытаюсь понять, с чего начать