0

I can't seem to figure this out.

I have a socket.io connection to my node server. When ever I emit a message I want to add it to an array and display that array as a scrollable list in the page.

Also what is a good place to declare this array?

import React from 'react';
import './App.css';
import socket from "./index.js";
import UpdateSocketInfo from './socketinfo';
//import statusInfoArray from "./socketinfo";

function App() {

    // where do I declare the array statusInfoArray? If i do it inside App it will be empty always?

  socket.on("uploadProgress", data => {
    statusInfoArray.push(data)
    console.log(data);
  });

  return (
    <div className="App">
      <UpdateSocketInfo statusInfoArray={statusInfoArray} />

    </div>
  );

}

export default App;

my socketinfo module

import React from 'react';

// set up status list, is this a good place to declare the array?
//const statusInfoArray= []
//export default statusInfoArray;

export const UpdateSocketInfo = props => {
    const statusInfoArray= props;
    const returnList = statusInfoArray.map((item) =>
    <li>
        <span>
            {item}
        </span>
    </li>
    );
    return (<ul>{returnList}</ul>)
}

3 Answers 3

1

I think you could use state variable in App component. Then pass array to UpdateSocketInfo via props. Something like:

App.js

import React, { useState } from 'react';
import './App.css';
import socket from "./index.js";
import UpdateSocketInfo from './socketinfo';
//import statusInfoArray from "./socketinfo";

function App() {

   const [statusInfoArray, setStatusInfoArray] = useState([]);

  socket.on("uploadProgress", data => {
    setStatusInfoArray(prevVals => [...prevVals, data]);
    console.log(data);
  });

  return (
    <div className="App">
      <UpdateSocketInfo statusInfoArray={statusInfoArray} />

    </div>
  );

}

export default App;

UpdateSocketInfo.js

import React from 'react';

export const UpdateSocketInfo = props => {
    const { statusInfoArray } = props;
   
    return (
      <ul>
         {statusInfoArray.map((item) => (
           <li>
             <span>
               {item}
             </span>
          </li>
         ))}
    </ul>
   );
}
Sign up to request clarification or add additional context in comments.

3 Comments

Works, but for some reason I can't explain I get a dozen of the same emit message in the list from socket.on("uploadProgress", data =>, and with @Tushar Shahi's answer I don't
Okay, I tried this with putting socket.on... inside useEffect hook and rendering it only once. This answer works actually better than any of the other answers. I want to give credit here. Oh and I have a also id for the array for the <li key=item.id></li>.
@eemilk You could always set my answer as the correct one =)
1

You want to update the view every time your variable changes, so it should be a state variable.

Once you have a state you cannot mutate it. So create a copy using ... and add data.

import React from 'react';
import './App.css';
import socket from "./index.js";
import UpdateSocketInfo from './socketinfo';
//import statusInfoArray from "./socketinfo";


function App() {
    const [statusInfoArray , setStatusInfoArray] = React.useState([]);
    // where do I declare the array statusInfoArray? If i do it inside App it will be empty always?

  socket.on("uploadProgress", data => {
    let newStatusInfoArray = [...statusInfoArray,data];
    setStatusInfoArray(newStatusInfoArray);
    console.log(data);
  });

  return (
    <div className="App">
      <UpdateSocketInfo statusInfoArray={statusInfoArray} />

    </div>
  );
}

1 Comment

This works great, thank you. Now I need to read more about state variables
0

Simple, use the React.useState

import React from 'react';
import './App.css';
import socket from "./index.js";
import UpdateSocketInfo from './socketinfo';
//import statusInfoArray from "./socketinfo";

function App() {

    // where do I declare the array statusInfoArray? If i do it inside App it will be empty always?

  const [statusInfoArray, setStatusInfoArray] = React.useState([]);

  socket.on("uploadProgress", data => {
    setStatusInfoArray(data);
    console.log(data);
  });

  return (
    <div className="App">
      <UpdateSocketInfo statusInfoArray={statusInfoArray} />

    </div>
  );

}

export default App;

1 Comment

I get a TypeError: statusInfoArray.map is not a function with setStatusInfoArray(data); and with @Tushar Shahi's answer I get the component to work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.