我目前正在尝试将类组件(正在工作)更改为功能组件(无法工作)。基本上,我的目标是使元素在页面上居中。
编辑:如果任何人都可以评论ref={tc=>(this.treeContainer=tc)}
的行为,那将也非常有帮助!
我的班级组件(有效):
/**
* Component returning a div containing a tree
* Need to declare as class for ComponentDidMount()
*/
class CenterMe extends React.PureComponent {
state={}
/* Used to center the tree on render */
componentDidMount() {
const dimensions = this.treeContainer.getBoundingClientRect();
this.setState({
translate: {
x: 30,
y: dimensions.height / 2
}
});
}
/* Returns the actual tree content */
render(){
return(
<div class="treeWrapper" ref={tc => (this.treeContainer = tc)}>
<Tree
translate = {this.state.translate}
/>
</div>
);
}
}
我当前的功能组件如下所示,并且不起作用:
function CenterMe() {
const [state, setState] = useState({translate:{x:0,y:0}); // Added thanks to @jstu
/* Used to center the tree on render */
useEffect(()=> {
const dimensions = treeContainer.getBoundingClientRect();
setState({
translate: {
x: 30,
y: dimensions.height / 2
}
});
});
/* Returns the actual tree content */
return(
<div class="treeWrapper" ref={tc => (this.treeContainer = tc)}>
<Tree
translate = {this.state.translate}
/>
</div>
);
}
更具体地说,它抱怨未定义setState和treeContainer。
如果重要的话,Tree组件是从react-d3-tree导入的,translate函数基本上按照它所说的进行操作-它移动了树。
我认为问题主要集中在ref={tc=>(this.treeContainer=tc)}
上,因此对此的解释也可能会有所帮助。非常感谢!
答案 0 :(得分:2)
您需要使用添加两个钩子useRef
和useState
来进行转换
function CenterMe() {
const [translate, setTranslate] = useState({ x: 0, y: 0 });
const treeContainer = useRef(null)
/* Used to center the tree on render */
useEffect(()=> {
const dimensions = treeContainer.current.getBoundingClientRect();
setTranslate({
x: 30,
y: dimensions.height / 2
});
}, []);
/* Returns the actual tree content */
return(
<div class="treeWrapper" ref={treeContainer}>
<Tree
translate={translate}
/>
</div>
);
}
useState将替换基于类的组件中的setState,如果您访问treeContainer.current键,useRef将为您提供当前引用。
要解释什么是ref部分,基本上,您的情况下的ref是引用dom节点,例如,如果您的树组件看起来像这样:
<div className="awesome-class">
<p>Hi</p>
</div>
这里的use ref所做的是,它将为您提供dom元素ref,假设树的组件与上面的示例类似,它将看起来像这样。
<div class="treeWrapper">
<div className="awesome-class">
<p>Hi</p>
</div>
</div>
使用ref可以从dom中获取元素,例如,在您的特定情况下getBoundingClientRect
将为您提供该特定元素的大小,如您所见,这非常有用,因为您能够使用父级组件中的子级值。在此处使用挂钩的更多信息:https://reactjs.org/docs/hooks-reference.html#useref
答案 1 :(得分:1)
所以您似乎错过了状态挂钩。试试这个
function CenterMe() {
const [state, setState] = useState({translate:{x:0,y:0}}); // Set an initial state
const treeContainer = useRef(null);
/* Used to center the tree on render */
useEffect(()=> {
const dimensions = treeContainer.current.getBoundingClientRect();
setState({
translate: {
x: 30,
y: dimensions.height / 2
}
});
},[]);
/* Returns the actual tree content */
return(
<div class="treeWrapper" ref={treeContainer}>
<Tree
translate = {state.translate}
/>
</div>
);
}
我还没有测试过。但是您缺少的是useState挂钩。 还只是注意到您的意思是要实现componentDidMount。因此您需要在最后传递一个空数组。使其表现为componentDidMount
答案 2 :(得分:1)
好,有几件事。 使用状态返回可以用语法[]解构的数组。像这样
const [someName, setSomeName] = useState({
translateX: 10,
translateY: 20
})
您正在给useState一个匿名函数。我不知道您是否可以做到,以前从未做到过。
但是尝试我上面写的解决方案。通过调用该方法来设置translatioY的值,然后在Tree组件中执行此操作。
<Tree translate = {someName}/>
对于ref,您必须使用useRef()钩子