Я пытаюсь построить этот TextArea
компонент, который использует React hook и styled-components
.
Все идет хорошо, когда мои textarea
набирают новые линии.Функция расширения работает, как и ожидалось.
В основном я делаю:
- Использование
textAreaRef
- useRef()
для сохранения ссылки на textarea
элемент - Использование
lastScrollHeight
- useRef()
для хранения последних ScrollHeight
- Использование
idealHeight
- useRef()
для хранения идеальной высоты для textarea
Я вычисляю idealHeight
на основе значения lastScrollHeight
, которое было сохранено в предыдущем рендере.Затем я сравниваю с текущим значением textAreaRef.current.scrollHeight
и вычисляю delta
.
Затем я вычисляю idealHeight.current = idealHeight.current + delta
и отправляю его как props
моему стилевому компоненту TextAreaInput
, чтобы установитьheight
.
ПРОБЛЕМА
scrollHeight
увеличивается при добавлении новых строк и возвращает положительное значение delta
.Но scrollHeight
не уменьшается при удалении строк.Итак, delta
возвращается к нулю.
Мне нужен способ измерить высоту текстового содержимого внутри textarea
.Здесь я видел некоторые вопросы о SO, которые рекомендовали сделать это, установив height
элемента в очень маленькое значение, прежде чем запрашивать scrollHeight
.
Действительно, это дает мне отрицательный deltas
, чтоЯ хочу, но это просто останавливает любое расширение или сжатие, и вместо этого я получаю полосу прокрутки.Посмотрите, переключая закомментированную строку textAreaRef.current.style.height = "2px";
.Некоторые, как компонент застревает на height='2px'
.Я не знаю.
Код SandBox с рабочим примером (обратите внимание на журналы консоли)
Есть идеи, что происходит?
TextArea.js
import React, { useRef } from "react";
import styled from "styled-components";
const TextAreaInput = styled.textarea`
height: ${props => props.idealHeight || "152px"};
min-height: 32px;
max-height: 320px;
line-height: 21px;
width: 100%;
resize: vertical;
box-sizing: border-box;
border: 1px solid rgb(217, 217, 217);
padding: 4px 11px;
text-size-adjust: 100%;
`;
function TextArea(props) {
const idealHeight = useRef(32);
const lastScrollHeight = useRef(30);
const textAreaRef = useRef(null);
console.log("ANOTHER RENDER...");
if (textAreaRef.current !== null && textAreaRef.current !== undefined) {
const scrollHeight = textAreaRef.current.scrollHeight;
// THIS NEXT LINE MAKES THE DELTA CALCULATION CORRECT ON 'SHRINKING'
// BUT STOPS THE RESIZING
// textAreaRef.current.style.height = "2px";
const delta = scrollHeight - lastScrollHeight.current;
console.log("Delta is: " + delta);
console.log("Last ScrollHeight: " + lastScrollHeight.current);
lastScrollHeight.current = scrollHeight;
console.log("Current ScrollHeight: " + lastScrollHeight.current);
idealHeight.current = idealHeight.current + delta;
console.log("IdealHeight :" + idealHeight.current);
}
return (
<TextAreaInput
placeholder={props.placeholder}
value={props.value}
onChange={e => props.setValue(e.target.value)}
ref={textAreaRef}
idealHeight={idealHeight.current + "px"}
/>
);
}
export default TextArea;