#reactjs #scroll #components #refactoring
#reactjs #прокрутите #Компоненты #рефакторинг
Вопрос:
Я создаю этот код:
import React from 'react'
import { range } from 'lodash'
const DIV_NUMBER = 5
export default class App extends React.Component {
constructor(props) {
super(props)
this.divs = []
}
handleScroll = divIdx => () => {
const divRef = this.divs[divIdx]
const left = divRef.scrollLeft
const top = divRef.scrollTop
this.divs.forEach(div => (div.scrollLeft = left))
this.divs.forEach(div => (div.scrollTop = top))
}
render() {
return (
<div style={{ border: '1px solid tomato' }}>
{range(DIV_NUMBER).map(i => {
return (
<div
key={i}
ref={divElem => (this.divs[i] = divElem)}
onScroll={this.handleScroll(i)}
style={{
width: 300,
height: 100,
margin: '2px',
overflow: 'auto',
border: '1px solid black',
}}
>
<div
style={{
width: 500,
height: 400,
}}
>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Scelerisque eu ultrices vitae auctor eu
augue ut lectus. In fermentum et sollicitudin ac orci. Velit sed ullamcorper morbi
tincidunt ornare. Auctor eu augue ut lectus arcu bibendum. Non nisi est sit amet.
Facilisis magna etiam tempor orci eu lobortis. Et tortor at risus viverra adipiscing
at in tellus integer. Lacus luctus accumsan tortor posuere ac ut consequat semper
viverra. Fermentum dui faucibus in ornare quam viverra orci sagittis. Porttitor eget
dolor morbi non. Pulvinar pellentesque habitant morbi tristique senectus et.
Tincidunt eget nullam non nisi est sit amet facilisis magna. Purus semper eget duis
at tellus at urna condimentum. Ipsum dolor sit amet consectetur adipiscing. Sit amet
aliquam id diam maecenas ultricies mi eget mauris. Faucibus scelerisque eleifend
donec pretium vulputate sapien nec sagittis. Tristique senectus et netus et
malesuada fames ac turpis. Egestas integer eget aliquet nibh. Enim ut tellus
elementum sagittis vitae. Urna condimentum mattis pellentesque id nibh tortor id
aliquet. Magna eget est lorem ipsum dolor. Felis imperdiet proin fermentum leo vel
orci porta. Eget egestas purus viverra accumsan in nisl nisi. Adipiscing commodo
elit at imperdiet. Facilisis magna etiam tempor orci eu lobortis. Volutpat est velit
egestas dui id ornare arcu odio. Praesent elementum facilisis leo vel fringilla.
Laoreet non curabitur gravida arcu ac tortor dignissim convallis aenean. Sodales ut
etiam sit amet nisl. Turpis massa tincidunt dui ut ornare. Viverra mauris in aliquam
sem fringilla ut morbi tincidunt augue.
</div>
</div>
)
})}
</div>
)
}
}
Это работает.
Он создает 5 элементов div, прокручивая один из них, прокручивая все div вместе. Для этого я использую ссылки React.
Что я хотел бы сделать сейчас, так это создать компонент, который абстрагирует эту логику.
Я представляю что-то вроде этого:
<ScrollDivs>
{range(DIV_NUMBER).map(i => {
return (
<div
key={i}
style={{
width: 500,
height: 400,
}}
>
all the text...
</div>
)
})}
</ScrollDivs>
Итак, волшебный компонент ScrollDivs
, который имеет дело с логикой.
Тому, кто использует этот компонент, не нужно беспокоиться о том, как это делается, ему просто нужно обернуть divs, которые хотят иметь возможность прокручивать вместе внутри этого компонента.
Как я могу сделать? Я не знаю, с чего начать.
Любая помощь приветствуется
Ответ №1:
React.Children.map
может помочь вам выполнить итерацию props.children
и React.cloneElement
может помочь с передачей новых реквизитов дочерним элементам:
export default class ScrollDivsSync extends React.Component {
divs = [];
handleScroll = e => {
const { scrollTop, scrollLeft } = e.target;
this.divs.forEach(div => {
div.scrollLeft = scrollLeft;
div.scrollTop = scrollTop;
});
};
render() {
const { children } = this.props;
let i = 0;
const enhancedChildren = React.Children.map(children, child =>
React.cloneElement(child, {
onScroll: this.handleScroll,
ref: divElem => (this.divs[i ] = divElem)
})
);
return enhancedChildren;
}
}
Это CodeSandbox с примером