I am trying to create ref in functional ponent .But getting different output as pare to to class based ponent
.
here is simple class based ponent
.In class based ponent I am getting correct refs
here is class based ponent .js
see ref mapping (correct ref mapping)
Same mapping I am trying to do with functional ponent but getting different output why ?
here is my function ponent .js
export default function App() {
useEffect(() => {
console.log('---', tabRefs);
}, []);
const getTabProps = ({ title, key, selected, tabIndex }) => ({
selected,
children: title,
key: tabPrefix + key,
id: tabPrefix + key,
ref: e => (tabRefs[tabPrefix + key] = e),
originalKey: key
});
I am getting this output
Why I am getting Ref from HTMLLIELEMENT instead of TAB
ponent ?
Update :
I am trying to get offsetWidth
still not able to get
.js
useEffect(() => {
console.log('---', tabRefs);
Object.keys(tabRefs).forEach(key => {
console.log(key);
if (tabRefs[key]) {
const width = tabRefs[key].tab.offsetWidth;
console.log(width);
}
});
}, []);
I am trying to create ref in functional ponent .But getting different output as pare to to class based ponent
.
here is simple class based ponent
.In class based ponent I am getting correct refs
here is class based ponent https://stackblitz./edit/react-vh86ou?file=src%2Ftabs.js
see ref mapping (correct ref mapping)
Same mapping I am trying to do with functional ponent but getting different output why ?
here is my function ponent https://stackblitz./edit/react-nagea2?file=src%2FApp.js
export default function App() {
useEffect(() => {
console.log('---', tabRefs);
}, []);
const getTabProps = ({ title, key, selected, tabIndex }) => ({
selected,
children: title,
key: tabPrefix + key,
id: tabPrefix + key,
ref: e => (tabRefs[tabPrefix + key] = e),
originalKey: key
});
I am getting this output
Why I am getting Ref from HTMLLIELEMENT instead of TAB
ponent ?
Update :
I am trying to get offsetWidth
still not able to get
https://stackblitz./edit/react-nagea2?file=src%2FApp.js
useEffect(() => {
console.log('---', tabRefs);
Object.keys(tabRefs).forEach(key => {
console.log(key);
if (tabRefs[key]) {
const width = tabRefs[key].tab.offsetWidth;
console.log(width);
}
});
}, []);
Share
Improve this question
edited Jul 4, 2021 at 22:56
Linda Paiste
42.3k8 gold badges79 silver badges116 bronze badges
asked Jul 4, 2021 at 1:13
user944513user944513
12.7k52 gold badges185 silver badges348 bronze badges
2 Answers
Reset to default 3You can't add the ref attribute to functional ponent for reasons as mentioned here. You can use forwardRef function bined with useImperativeHandle hook to emulate class ponent ref, but you can't add ref to your Tab ponent as long as Tab is a function ponent.
For example, you can add some code to your Tab ponent like below.
const Tab = React.forwardRef(({ children }, ref) => {
const liRef = useRef(null);
React.useImperativeHandle(ref, () => ({
tab: liRef.current
}));
return <li ref={liRef}>{children}</li>;
});
export default Tab;
If you want to store all refs of all Tab ponent and call some functions of it later, you can add functions inside useImperativeHandle hook.
As explained by @TabW, function ponents do not have refs. But you don't need a ref to the Tab
ponent itself. You can get the offsetWidth
of the underlying li
element just by forwarding the ref, without having to use useImperativeHandle
.
Attach your forwarded ref directly on the li
:
const Tab = React.forwardRef(({ children }, ref) => {
return <li ref={ref}>{children}</li>;
});
And remove the .tab
property from where you access it.