javascriptnode.jsreactjswebsocketreact-state

My React Component not re-render when my array object properties is changed


Hello I'm just new in React. I have a react component that shows list users. The data was from array of object. When I fetched new data that changed the properties in object the component was not re-render. How to solve that problem ?

Here's my code :

homepage.js

...
const [users, setUsers] = useState([])

async function connWS() {
ws.onmessage = async function(message) {
  var parsedMessage = JSON.parse(message.data);
  console.info('Received message: ' + message.data);
        
  switch (parsedMessage.id) {
   case 'updateListUser':
   setUsers(parsedMessage.users);
  break;
}

useEffect(() => {
  async function init() {
    await connWS();
  }
  init();
}, []);

    return (
        <Layout
            isVideoCall={false}
            rightSection={
            <Users data={users} />
        </Layout>
    );

Users.js

const Users = ({data}) => {
return (
        <div className={styled.users}>
            {data.map((user) => (
                <div className={styled.userItem}>
                    {user.imageUrl ? (
                        <img src={""} alt={user.name} />
                    ) : (
                        <span style={{ backgroundColor: `#13c2c2` }}>
                            {user.shortName}
                        </span>
                    )}
                    <p>{user.name}</p>
                    {user.state ? (
                        user.state === 'REGISTERED' || 'registered' ? (
                            <p style={{ color: `#13c2c2` }}>Online</p>
                        ) : (
                            <p style={{ color: `#f5222d` }}>Offline</p>
                        )
                    ) : (
                        <p style={{ color: `#f5222d` }}>Offline</p>
                    )}
                    
                    <div className={styled.overlay}>
                        <Button
                            className={styled.callBtn}
                            type="dashed"
                            size="large"
                            icon={
                                <Icon name="call" width={24} height={24} />
                            }
                            ghost
                            onClick={() => onClickCall(user.name)}
                        >
                            Call
                        </Button>
                    </div>
                </div>
            ))}
        </div>
    );
};
}

Here's is the example of the users data look like.

const users = [
        {
            name: 'Josh',
            state: 'registered'
        },
        {
            name: 'Mike',
            state: 'in_call'
        }
    ]

I was trying to update the status users in list where they online/offline using websocket for realtime update. When I get the data from server that only change the state properties, but the component is not re-render.

I was trying to resolve using different refference memory that create a new array of object using new data but i still didn't work.


Solution

  • As I look, you are correctly using the setUsers function provided by the useState hook to update the state. This should cause a re-render of the component, however, there are a few things you might want to check.

    1. Ensure that your ws connection is open and actively sending messages.
    2. Ensure that in your onmessage handler, you are expecting a property users in parsedMessage.
    3. Check if you are updating nested properties in your state.

    One final note is about your conditional rendering code for the user state. The condition user.state === 'REGISTERED' || 'registered' will always evaluate to true because 'registered' is a truthy value in JavaScript. You might want to change this to 'user.state==='REGISTERED' || user.state === 'registered' for the intended behavior.

    Hope this answer would give you a hint.