2

I have a list in my application which is created from two related tables(products and stocks). I want to order items by date which is in the Stocks table. My API returns well ordered list but in my app the list is not ordered. When I try to order by any of Products fields it works fine - also in react.

My view:

class StocksView(viewsets.ModelViewSet):
    serializer_class = StocksSerializer
    ordering_fields = ['date']
    filter_backends = (filters.OrderingFilter,)
    def get_queryset(self):
        queryset = Stocks.objects.all().order_by('date')
        return queryset
    def perform_create(self, serializer):
        serializer.save(user=self.request.user)

Method from React:

  const fetchStocks = async () => {
    try {
      const response = await axiosInstance.get('/stocks/?ordering=date')
      if (response) {
        setStocksInfo(response.data)
        console.log(response.data)
      }
    } catch (error) {
      throw error;
    }
  }

And returned list from two merged tables:

{productsInfo.map(products => {
                  const product = stocksInfo.filter(e => e.product_id === products.product_id);
                  return (
                    product.map((stock, i) => (
                      <tr key={i} className="table-data">
                        <td className="col-3"> {products.name}</td>
                        <td className="col-3">{stock.date}</td>
                        <td className="col-1">{stock.count}</td>
                      </tr>
                    ))
                  )
                })}
3
  • How are you rendering that information in react? Commented Sep 21, 2021 at 22:37
  • @PietroNadalini I added how I connect it in html Commented Sep 21, 2021 at 22:50
  • How are you calling fetchStocks? Using useEffect? Do you see the request going out in the Network tab of the developer tools? Does it return with the expected body? Commented Sep 21, 2021 at 23:06

1 Answer 1

1

Since you want to order based on the Stocks table, you should do the map from that array first.

You can make an implementation like this one, where you filter the stocks so it only has the ones matching from the productsInfo, and then mapping it.

{stocksInfo
    .filter(e => productsInfo.some(p => p.product_id === e.product_id))
    .map((stock, i) => {
        const products = productsInfo.find(e => e.product_id === stock.product_id);
        return (
            <tr key={i} className="table-data">
                <td className="col-3"> {products.name}</td>
                <td className="col-3">{stock.date}</td>
                <td className="col-1">{stock.count}</td>
            </tr>
        );
    })}

But, since that is inefficient, I would recommend combining both arrays and then mapping them. You can combine them with this code:

const combination = stocksInfo
    .map(item =>
        Object.assign(
            item,
            productsInfo.find(({product_id}) => product_id === item.product_id)
        )
    )
    .filter(item => item.name);

I also added a working example here:

const stocksInfo = [
    {date: "date1", count: 1, product_id: 123},
    {date: "date2", count: 2, product_id: 321},
    {date: "date3", count: 3, product_id: 331},
    {date: "date4", count: 4, product_id: 341},
];
const productsInfo = [
    {name: "test4", product_id: 341},
    {name: "test2", product_id: 321},
];

const combination = stocksInfo
        .map(item =>
            Object.assign(
                item,
                productsInfo.find(({product_id}) => product_id === item.product_id)
            )
        )
        .filter(item => item.name);


const Example = ({title}) => {

 return (
        <div>
            previous way
            <table>
                {productsInfo.map(products => {
                    const product = stocksInfo.filter(e => e.product_id === products.product_id);
                    return product.map((stock, i) => (
                        <tr key={i} className="table-data">
                            <td className="col-3"> {products.name}</td>
                            <td className="col-3">{stock.date}</td>
                            <td className="col-1">{stock.count}</td>
                        </tr>
                    ));
                })}
            </table>
            new way
            <table>
                {combination.map((stock, i) => {
                    return (
                        <tr key={i} className="table-data">
                            <td className="col-3"> {stock.name}</td>
                            <td className="col-3">{stock.date}</td>
                            <td className="col-1">{stock.count}</td>
                        </tr>
                    );
                })}
            </table>
        </div>
    );
};

// Render it
ReactDOM.render(
  <Example title="Example using Hooks:" />,
  document.getElementById("react")
);
table, td {
  border: 1px solid black;
  padding: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>

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

1 Comment

thank you! I didn't think about combining my tables like this. Now it works like a charm

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.