1

Hi I'm new to Node/React, and I'm creating a learning project. It's platform that connects freelancers with nonprofit companies. Users (freelancers), view a list of companies, and click a button to connect to a company. Once this is clicked, the user will have that company added as a relationship in the database. This is working correctly.

Now I'd like users to visit a page and view their "connections", basically all the companies they connected with. In the database, I'm only storing the "companyHandle" in the association table. So currentUser.connections would give me an array of companyHandles ['aapl', 'gogl', 'msft']. So when the user views their connections, I would like to fetch data from the backend API, to retrieve more information about each company (companyName, numEmployees, etc..).

I tried to do that by looping through all the companyHandles, and fetching data from the API for each company, but I get the error React Hook "useEffect" may be executed more than once. Possibly because it is called in a loop...

What's a better way to do this? How can I fetch data for different companies? Below is my code (shortened)

schema

CREATE TABLE companies (
  company_handle VARCHAR(25) PRIMARY KEY,
  password TEXT NOT NULL,
  company_name TEXT NOT NULL,
  country TEXT NOT NULL,
  num_employees INTEGER CHECK (num_employees > 0)
);

CREATE TABLE users (
  username VARCHAR(25) PRIMARY KEY,
  password TEXT NOT NULL,
  first_name TEXT NOT NULL,
  last_name TEXT NOT NULL,
  email TEXT NOT NULL CHECK (position('@' IN email) > 1)
);

CREATE TABLE connections (
  username VARCHAR(25)
    REFERENCES users ON DELETE CASCADE,
  company_handle VARCHAR(25)
    REFERENCES companies ON DELETE CASCADE,
  PRIMARY KEY (username, company_handle)
);

UserConnections.js

function UserConnections() {
  const { currentUser } = useContext(UserContext);
  const connections = currentUser.connections;
  const [companies, setCompany] = useState([]);

  if (connections) {
    for (const connection in connections) {
      useEffect(function getCompanyDetail() {
        async function getCompany() {
          setCompany(await VolunteerApi.getCurrentCompany(connection));
        }
        getCompany();
      }, [connection]);
    }
  }

  return (
    <div>
      {companies.length
        ? (
          <div>
            {companies.map(company => (
              <CompanyCard
                key={company.companyHandle}
                companyHandle={company.companyHandle}
                companyName={company.companyName}
                country={company.country}
                numEmployees={company.numEmployees}
              />
            )
            )}

          </div>
        ) : (
          <p>You have no connections</p>
        )}
    </div>
  );
};

2 Answers 2

2

You can use promise.all to execute promises (api fetcher) and useEffect hook from React.

useEffect(() => {
   setLoading(true); // If you want to add loader or spinner till companies info fetched
   const connectionsPromises = connections.map((connection) => {
     return VolunteerApi.getCurrentCompany(connection);
   });

   Promise.all(connectionsPromises).then((companies) => {
      setCompany(companies); // save companies 
      setLoading(false); // disable loader 
   });
}, [connections])

Promise.all resolves promises parallelly

Sign up to request clarification or add additional context in comments.

Comments

0

Basically, you can only use hooks at the top level of your component.

Take a look at the rules of hooks (including useEffect).

You should try to put your if and for loop inside the useEffect.

Comments

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.