cannot read Property 'Join' of Undefined - React

Asked

Viewed 133 times

-1

I’m getting this problem when I try to submit a form with React on the front and Node on the backend. This form registers a store. When clicking save, he was to take the categories of the store and make sure they are grouped (Join) with a "," and a space between them:

 <span>{shop.shopCategories.join(', ')}</span>

The complete code of where the error occurs is below:

import React from 'react';

import './style.css';

function ShopItem({shop}) {
  return (
    <li className="shop-item">
      <header>
        <img src='https://jornalggn.com.br/sites/default/files/u16/imagem-sem-foto-de-perfil-do-facebook-1348864936180_956x5001.jpg' alt= {shop.shopFantasyName} /> 
          <div className= "shop-info">
            <strong>{shop.shopName}</strong>
            <span>{shop.shopCategories.join(', ')}</span>   // ESSA É A LINHA APONTADA NO ERRO //
          </div>
      </header>
  <p>sobre a loja</p>
  <a href= "http://www.google.com"> Acessar todos os produtos de {shop.shopFantasyName}</a>
  </li>
  )
}

export default ShopItem; 

The strange thing is that after reloading the page, the store is saved in the bank and is shown on the page of registered stores, IE, this error does not prevent to register the store.

This is my post route:

    async store(req, res) {
        const {shopName, shopEmail, shopCNPJ, shopFantasyName, shopPhoneNumber, shopCategories, latitude, longitude} = req.body;

        let shop = await Shop.findOne({shopCNPJ});

        if(!shop) {

            const shopCategoriesArray = parseStringAsArray(shopCategories);

            const shopLocation = {
                type: 'Point',
                coordinates: [longitude, latitude],
            };

            shop = await Shop.create({

                shopLocation,
                shopCategories: shopCategoriesArray,
                shopName,
                shopEmail,
                shopCNPJ,
                shopFantasyName,
                shopPhoneNumber,


            })
            console.log(shopCategoriesArray);
        }

      return res.json({shop:[]});
    }
};

And this is the controller:

import React, {useState, useEffect} from 'react';
import api from './services/api';

import './global.css';
import './App.css';
import './Sidebar.css';
import './Main.css';

import ShopItem from './components/ShopItem';
import ShopForm from './components/ShopForm';

function App() {

  const [shops, setShops] = useState([]);

  
  useEffect(()=>{  
    async function loadShops() {
      const res = await api.get('/shops');

      setShops(res.data);
    }
    loadShops();
  }, []);

  
  async function handleAddShop(data) {
    const res = await api.post('/shops', data)
    
  setShops([...shops, res.data])
}

  
    
  return (
    <div id="app">
      <header >
        <head> 
          <p>
            teste
          </p>
        </head>
      </header>
      <aside>
          <strong> Cadastre sua empresa</strong>
          <ShopForm onSubmit={handleAddShop}/>
      </aside>
      <main>
        <ul>
          {shops.map(shop => (
             <ShopItem key={shop._id}  shop={shop}/>
          ))}
        </ul>
      </main>
      <footer>

      </footer>
    </div>
  
  );
}

export default App;

I don’t know what else to do!! Someone gives me a help, every time I save a store the error occurs!

1 answer

1


At least in the code snippet posted on your route to POST /shops, looks like you’re doing:

return res.json({ shop: [] });

That is, at the end of the insertion of the new store, you simply send as a response an object that has a field called shop, what door a array empty.

If this route corresponds to:

await api.post('/shops', data)

So, you can say that you are taking this object and mixing it with the other stores. That is to say:

setShops( [ ...shops, res.data ] );
// seria o mesmo que:
// setShops( [ ...shops, { shop: [] } ] );

So when you do:

shops.map( shop => ( ... ) )

There will come a point where shop will correspond to the { shop: [] }.

Consequently, when you do shop.shopCategories (and I think not only this field, but, if so, with all the others it also happens), returns undefined. So that:

<span>{shop.shopCategories.join(', ')}</span>

Becomes the same as:

<span>{(undefined).join(', ')}</span>

What causes the error.


Thus, one way to resolve this would be to carry out the requisition POST only for register the stores, and then would use the function loadShops for carry the shops:

async function loadShops() {
  const res = await api.get('/shops');

  setShops(res.data);
}

useEffect(loadShops, []);

async function handleAddShop(data) {
    const res = await api.post('/shops', data);
        
    await loadShops();
}

Which would even make things better apart: handleAddShop makes the insertion of a new store; and loadShops charges to list of shops. However, this alternative could bring about some change in the performance and response time of the application, as it would consist of an unnecessary (perhaps) upgrade of the other stores.

Therefore, another alternative is to simply replace the object { shop: [] } by the variable itself shop, which will consist of the last store added:

return res.json(shop);

But remember, if you don’t

if (!shop) {

It’ll mean the store already exists in the database. And if it already exists, then the user who tried to add should be aware of it, to exactly avoid the existence of duplicated data, and might even suggest a possible way to update that store, rather than reinserting it - functionality, including, that if there is no longer, you could create (of course, again I say, if you prefer).

I hope I’ve helped!

  • I’ve been in this trouble for a while, all I’ve done is turn this: return res.json({ shop: [] }); therein: return res.json(shop); I didn’t change anything on the front, only on the route! Thank you very much because it was through your help that I realized where the problem was!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.