Home > Software engineering >  Why I'm getting "Not Found: /api/products/undefined" instead of /api/products/1?
Why I'm getting "Not Found: /api/products/undefined" instead of /api/products/1?

Time:08-08

I want to get data of a single product from "api/products/id" (I'm using Django Rest Framework) and put them into redux store, so when I refresh product's page the data will be actually displayed.
The problem is, when I go to "localhost:3000/products/1" (I'm using also React) instead of getting product with id = 1, I get undefined product and no data at all. The deeper point I've found where id is undefined is in views.py

Why this problem occurs? It has some connection with migration? I deleted database *.pyc *.py files except init and then once again run makemigrations and migrate but nothing changed.

And how can I solve it?

Browser's consol: Browser's consol

VS Code terminal enter image description here

EDIT - added front-end So if the problem is with front-end, then it should be probably during fetching. The request URL seems good to me and I don't see misspelling. In fetchSingleProduct is only part of the url. The other part is set in package.json as a: "proxy": "http://127.0.0.1:8000",

singleProductSlice

const initialState = {
    status: 'idle',
    error: null,
    product: {
        reviews: [],
    }
}

const singleProductSlice = createSlice({
    name: 'singleProduct',
    initialState,
    reducers: {

    },
    extraReducers(builder) {
        builder
            .addCase(fetchSingleProduct.pending, (state, action) => {
                state.status = "loading"
            })

            // I've fetched the data! I will add them to current state
            .addCase(fetchSingleProduct.fulfilled, (state, action) => {
                if(action.payload.message) {
                    state.status = "failed"
                    state.error = action.payload.message
                } else {
                    state.status = "succeeded"
                    state.product = action.payload
                }
            })
    }

})

// Fetch details about particular product, so when we refresh 
// page about particular product we won't have to depend on data from
// higher level component
export const fetchSingleProduct = createAsyncThunk('products/fetchSingleProducts', async (id) => {
    try {
        const response = await axios.get(`/api/products/${id}`)
        console.log(response.data)
        return response.data
    } catch (error) {
        return error.message
    }

})

export default singleProductSlice.reducer

export const selectSingleProduct = state => state.product 

ProductScreen.js

// This is component that display data of a single product
function ProductScreen() {
    const productId = useParams().id    // I get id of the product
    console.log("Product id: ", productId)
    const product1 = useSelector(selectSingleProduct)   // I'm searching for pro
    console.log("Product: ", product1)
    // I created empty product so there will be less errors until solving the problem
    const product = {  
        reviews: []
    }

    const dispatch = useDispatch()

    const status = useSelector(state => state.singleProduct.status)

    useEffect((productId) => {
        // If client doesn't have any data from server...
        if(status === 'idle') {
        // ...fetch for this data
            dispatch(fetchSingleProduct(productId))
        }
    }, [status, dispatch]) 

App.js

<Routes>
   <Route path='/' element={<HomeScreen />} exact />
   <Route path='/products/:id' element={<ProductScreen />} />
</Routes>

views.py

@api_view(['GET'])
def getProduct(request, pk):

    print("\n\n\nPlural key: ", pk) # The pk is undefined
    product = Product.objects.get(id=pk) # So the product also is undefined
    serializer = ProductSerializer(product, many=False)
    return Response(serializer.data)

serializer.py

class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = '__all__'    

models.py

from django.contrib.auth.models import User

class Product(models.Model):
    # ID is generating automatically
    user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
    name = models.CharField(max_length=200, null=True, blank=True)
    image = models.ImageField(null=True, blank=True,
                              default='/placeholder.png')
    brand = models.CharField(max_length=200, null=True, blank=True)
    category = models.CharField(max_length=200, null=True, blank=True)
    description = models.TextField(null=True, blank=True)
    rating = models.DecimalField(
        max_digits=7, decimal_places=2, null=True, blank=True)
    numReviews = models.IntegerField(null=True, blank=True, default=0)
    price = models.DecimalField(
        max_digits=7, decimal_places=2, null=True, blank=True)
    countInStock = models.IntegerField(null=True, blank=True, default=0)
    createdAt = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.name

urls.py

urlpatterns = [
    path('', views.getRoutes, name='routes'),
    path('products/', views.getProducts, name='products'),
    path('products/<int:pk>', views.getProduct, name='product'),
]

Originally was <str:pk> but it throwed ValueError, so changed to <int:pk>.

CodePudding user response:

Your Back-end code seems fine. what I believe is happening is that your front-end (fetchSingleProduct function) is not getting the product id that it needs.


Update from the OP.

The reason why it is not getting the product id is because in useEffect "productId" is passed as an argument to arrow function. But since this function is never called outside its declaration, the arrow function doesn't get any id, so it gets "undefined" instead.

To solve this, please remove "productId" argument from arrow function. The code will work after this, but there will be warning:

React Hook useEffect has a missing dependency: 'productId'. Either include it or remove the dependency array react-hooks/exhaustive-deps

To get ride of it, just pass "productId" to the array, that is useEffect's second argument.
For details check: React Hook useEffect has missing dependencies. Either include them or remove the dependency array react-hooks/exhaustive-deps

The useEffect's code after changes will look like this:

useEffect(() => {
        // If client doesn't have any data from server...
        if(status === 'idle') {
        // ...fetch for this data
        dispatch(fetchSingleProduct(productId))
        }
    }, [status, dispatch, productId]) 

CodePudding user response:

I think there must be a problem in react. Please make sure the request API url is correct. There is no problem in the backend side code.

  • Related