Reputation: 1554
I'm using React's hooks (version 16.8.6) to inject an array of buttons with their respective index + value + onClick={}.
function App() {
const [rooms, setRoomArray] = useState([]);
const roomArray = [
'room1',
'room2',
'room3',
'room4',
];
const handleNewMessage = (room) => {
setRoomArray(roomArray);
roomSpawner(rooms);
};
const test = () =>{
console.log('test here');
}
const roomSpawner = (rooms) =>{
return rooms.map((value,index) => (
<button onClick={test()} key={index}>{value}</button>
));
};
Everything works and displays properly, yet by console logging, I see that my console is going into a loop there is a loop and i'm trying to understand:
test()
a socket connection polling a remote server?Upvotes: 2
Views: 177
Reputation: 31425
Q1: Is this is a loop or is it react's regular polling/reactive behavior?
Answer: As commenters have pointed out, the loop is being caused by onClick={test()}
. The onClick
prop expects a function, and not a function call, to attach as an event handler. What it you can do is something like this:
const test = (index) =>{
console.log('I was called for room number: ' + index);
}
const roomSpawner = (rooms) =>{
return rooms.map((value,index) => (
<button onClick={() => test(index)} key={index}>{value}</button>
));
Q2: Is this 'expensive' in terms of performance?
Not at all. This is a perfect valid React implementation.
Q3: Would it make sense to insert into test() a socket connection polling a remote server?
I don't think so. You should insert your socket connection inside a useEffect()
hook to be connected on mount. Something like this:
// INSIDE YOUR COMPONENT
useEffect(()=> {
// CONNECT TO SOCKET
// ON SOCKET MESSAGES, UPDATE SOME STATE WITH THE NEW ROOMS AND COMPONEN WILL RE-RENDER
return () => {
// DISCONNECT FROM SOCKET
}
},[]); // WITH THIS EMPTY ARRAY, THIS EFFECT WILL RUN ON 1ST RENDER, AND IT WILL DISCONECT FROM YOUR SOCKET WHEN IT GETS DISMOUNTED
Q4: Am I misusing the construct? If so please show me how to properly inject an array of elements.
I think you're fine. Keep the array of rooms in a state variable using useState()
and use stateWithArrayOfRooms.map()
to generate your components (buttons, or whatever). Something like.
// INSIDE YOUR COMPONENT
const [roomsArray, setRoomsArray] = useState([]);
useEffect(()=>{
// CONNECT TO YOUR SOCKET AND UPDATE roomsArray with new messages.
// setRoomsArray('newRoomsArray from socket');
return () => {
// DISCONNECT FROM SOCKET
}
},[]);
const roomItems = roomsArray.map((item, index) =>
<RoomComponent key={index or some other unique id} onClick={()=>test(index)}/>
);
return (
<RoomsContainer>
{roomItems}
</RoomsContainer>
);
Upvotes: 1