Reactjs 在功能组件上设置ref
我试图将这个基于类的react组件更改为函数组件,但在设置引用时遇到了一个无限循环问题,我认为这是因为在每次渲染时,ref都是一个新对象 如何将基于类的组件转换为功能组件 index-class.js-Reactjs 在功能组件上设置ref,reactjs,Reactjs,我试图将这个基于类的react组件更改为函数组件,但在设置引用时遇到了一个无限循环问题,我认为这是因为在每次渲染时,ref都是一个新对象 如何将基于类的组件转换为功能组件 index-class.js- 这里的问题是通过setState和useffect(这就是导致无限循环的原因)将引用设置为更新 在功能组件上设置引用的方法如下: const组件=()=>{ const ref=useRef(空) 返回( ) } 更多信息可以在这里找到:那么我应该如何在我的功能组件中重写它,使其像上面所示的类
这里的问题是通过setState和useffect(这就是导致无限循环的原因)将引用设置为更新 在功能组件上设置引用的方法如下:
const组件=()=>{
const ref=useRef(空)
返回(
)
}
更多信息可以在这里找到:那么我应该如何在我的功能组件中重写它,使其像上面所示的类组件一样工作-像您那样转换组件,复制我共享的代码,并从
setState
中删除ref,此外,您还可以删除setInnerRef
函数,因为该函数将不再使用。如果您想获取高度状态的上一个值,而不是使用usePrevious
函数,您可以在需要设置新状态时随时访问该函数:setState((prevState)=>console.log(“prevState”)
,谢谢@ale,我没有得到错误,但我没有得到平滑过渡效果,它没有在点击时切换回来,我在这里错过了什么?但是在基于类的组件中,它的工作不用担心!当您需要访问引用的元素时,它无法正常工作,您需要使用ref.current
来访问它,而不仅仅是ref
。另外,还有一个错误,您忘记将状态从类(在其中使用this.state)更新为函数组件(在其中只调用setState函数)。工作沙箱:
class Collapse extends React.Component {
constructor(props) {
super(props);
this.state = {
showContent: false,
height: "0px",
myRef: null,
};
}
componentDidUpdate = (prevProps, prevState) => {
if (prevState.height === "auto" && this.state.height !== "auto") {
setTimeout(() => this.setState({ height: "0px" }), 1);
}
}
setInnerRef = (ref) => this.setState({ myRef: ref });
toggleOpenClose = () => this.setState({
showContent: !this.state.showContent,
height: this.state.myRef.scrollHeight,
});
updateAfterTransition = () => {
if (this.state.showContent) {
this.setState({ height: "auto" });
}
};
render() {
const { title, children } = this.props;
return (
<div>
<h2 onClick={() => this.toggleOpenClose()}>
Example
</h2>
<div
ref={this.setInnerRef}
onTransitionEnd={() => this.updateAfterTransition()}
style={{
height: this.state.height,
overflow: "hidden",
transition: "height 250ms linear 0s",
}}
>
{children}
</div>
</div>
);
}
}
import React, { useEffect, useState } from "react";
import { usePrevious } from "./usePrevious";
const Collapse = (props) => {
const { title, children } = props || {};
const [state, setState] = useState({
showContent: false,
height: "0px",
myRef: null
});
const previousHeight = usePrevious(state.height);
useEffect(() => {
if (previousHeight === "auto" && state.height !== "auto") {
setTimeout(
() => setState((prevState) => ({ ...prevState, height: "0px" })),
1
);
}
}, [previousHeight, state.height]);
const setInnerRef = (ref) =>
setState((prevState) => ({ ...prevState, myRef: ref }));
const toggleOpenClose = () =>
setState((prevState) => ({
...prevState,
showContent: !state.showContent,
height: state.myRef.scrollHeight
}));
const updateAfterTransition = () => {
if (state.showContent) {
this.setState((prevState) => ({ ...prevState, height: "auto" }));
}
};
return (
<div>
<h2 onClick={toggleOpenClose}>{title}</h2>
<div
ref={setInnerRef}
onTransitionEnd={updateAfterTransition}
style={{
height: state.height,
overflow: "hidden",
transition: "height 250ms linear 0s"
}}
>
{children}
</div>
</div>
);
};
import { useRef, useEffect } from "react";
function usePrevious(value) {
const ref = useRef();
useEffect(() => {
ref.current = value;
}, [value]);
return ref.current;
}
export { usePrevious };