Reputation: 3678
i am trying to covert a small jquery component to react .but i am getting this issue Cannot read property 'offsetWidth' of null
here is jquery simple component http://jsfiddle.net/abhitalks/860LzgLL/
what component does it show "menu or tab list" .If window screen is decrease it hide menu and move to dropdown like this
I tried to implement is react .
My approach is
li
's or sum of all width of li.set the threshold
. render using threshold valuebut when I am resize my component I am getting below error
**Cannot read property 'offsetWidth' of null **
here is my code https://stackblitz.com/edit/react-wmtunp?file=src%2FApp.js
import React, { useState, useRef, createRef, useEffect } from 'react';
import './style.css';
const data = [
'Option One',
'Option_hellodummyhhhsdshshshd',
'Option Three',
'Option Four',
'Option Five'
];
export default function App() {
const [state, setState] = useState(data);
const [threshold, setThreshold] = useState(-1);
const liRefs = useRef([]);
const ulRef = useRef(null);
liRefs.current = state.map((_, i) => liRefs.current[i] ?? createRef());
const adjustItems = function() {
var skipLoop = false,
w2W = ulRef.current.offsetWidth,
index = -1,
totalW = 0;
liRefs.current.map(function(li, key) {
if (skipLoop) {
return;
}
totalW += li.current.offsetWidth;
if (totalW > w2W) {
skipLoop = true;
index = key;
}
setThreshold(index);
});
};
useEffect(() => {
adjustItems();
window.addEventListener('resize', adjustItems);
return () => window.removeEventListener('resize', adjustItems);
}, []);
return (
<div>
<ul id="menu" ref={ulRef}>
{state.map((i, index) =>
threshold == -1 ? (
<li ref={liRefs.current[index]} key={index}>
{i}
</li>
) : threshold !== -1 && threshold >= index ? (
<li ref={liRefs.current[index]} key={index}>
{i}
</li>
) : (
<></>
)
)}
</ul>
<ol>
<li>
Collected
<ul id="submenu">
{state.map((i, index) =>
threshold !== -1 && threshold <= index ? (
<li ref={liRefs.current[index]} key={index}>
{i}
</li>
) : (
<></>
)
)}
</ul>
</li>
</ol>
</div>
);
}
My functionality break when I am resizing the window. I am new in react js .Is there problem in my approach ? any suggestion ?
Upvotes: 0
Views: 3709
Reputation: 131
Just try using ? this operator, since when you are resizing it might get null or undefined based on condition but by putting this condition it will help you put an "and" check if property value exists or not.
import React, { useState, useRef, createRef, useEffect } from 'react';
import './style.css';
const data = [
'Option One',
'Option_hellodummyhhhsdshshshd',
'Option Three',
'Option Four',
'Option Five'
];
export default function App() {
const [state, setState] = useState(data);
const [threshold, setThreshold] = useState(-1);
const liRefs = useRef([]);
const ulRef = useRef(null);
liRefs.current = state.map((_, i) => liRefs.current[i] ?? createRef());
const adjustItems = function() {
let skipLoop = false,
w2W = ulRef.current.offsetWidth,
totalW = 0;
liRefs.current.map((li, key) => {
if (skipLoop) {
return;
}
totalW += li?.current?.offsetWidth;
if (totalW > w2W) {
skipLoop = true;
setThreshold(key);
} else {
setThreshold(liRefs.current.length);
}
});
};
useEffect(() => {
adjustItems();
window.addEventListener('resize', adjustItems);
return () => window.removeEventListener('resize', adjustItems);
}, []);
return (
<div>
<ul id="menu" ref={ulRef}>
{state.map((i, index) =>
threshold == -1 ? (
<li ref={liRefs.current[index]} key={index}>
{i}
</li>
) : threshold !== -1 && threshold > index ? (
<li ref={liRefs.current[index]} key={index}>
{i}
</li>
) : (
<></>
)
)}
</ul>
<ol>
<li>
Collected
<ul id="submenu">
{state.map((i, index) =>
threshold !== -1 && threshold <= index ? (
<li ref={liRefs.current[index]} key={index}>
{i}
</li>
) : (
<></>
)
)}
</ul>
</li>
</ol>
</div>
);
}
You can reference it https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining
Upvotes: 2