How to solve duplicating update in Vuejs 2 component

I have a child component “DetailsDialog” in which I watch for a prop change and then request an API call. The problem is that the API call is executing twice instead of once, so, I believe is because the component is updating double. I am using VueJS 2.7, OptionsAPI and basically I just want that when I click a row in a datatable the app call an API to show data dynamically. I even called updated() hook and inside a console.log and indeed, is updating twice. So, I need to call the API just once in the component when its prop is updated. I’d appreciate the help, thanks in advance

// Component child DialogDetails.vue
props: {
    // other props {...},
    // desired prop
    selected_company: {
        type: Object,
        default() {
            return {}
        }
    },
},

watch: {
    selected_company(val) {
        if (val !== null) {
            this.apiCall()
        }
    },
},

// Event in other sibling component
rowClick: function (item, row) {
        this.$emit('openDetailsModal', {selected_user: null, selected_company: item, open_details: true})
    },

// Parent component     
<dialog-details :show-details-modal="open_details"
                :selected_company="selected_company" 
                @closeDialog="closeDetails" />

How to i get object key value in typescript & also this string compare the other like modify or not check? [closed]

In Typescript

i need the object in key but in my case, i need the specific key like key is jonnny so i find the last word nny to find this key so it possible to find this key and this is only one key this type so how to find this key please help and give me the best way and short using build function

I found all the articles but did not get this type of information

How can I make an ajax call asynchronously from Javascript to mvc controller method and to wait for the result to proceed to next line of code

I am trying to get the result from the function called ‘validateScheduleDate()’ and only if the result comes from the function, then next line of code should be executed. I am trying to validate two dates to find these dates are between the given time frame.

Right now, it does not wait for the result from the function called ‘validateScheduleDate’

Here is my code in Jvascript

$wizard.wizard({
    validateTab: function (currentTab) {
        validateScheduleDate().then(function (data) {

            if (data != 'noDifference') {
                // Not passed to the next line                       
            }

        }); 

        switch (currentTab.index()) {
            case 0: // tabPaneNames.general
                return  validateSales1()
            case 1: // tabPaneNames.problems
                return  validateSales2()
            case 2: // tabPaneNames.serviceProviders
                return  validateSales3()           
            default:
                return false;
        }
    }
});
  $('[submit-sales').click(function (event) {
      event.preventDefault();  
      
      validateScheduleDate().then(function (data) {

          if (data == 'noDifference') {
              validateTabs(function () { submitForm(); }, true);
          }
          else{
                 // Not passed to the next line
              }

           
      });
 
  });   


 function validateScheduleDate() {
     var startDate = document.getElementById('dispatch-start-date').value;
     var startTime = document.getElementById('ddl-dispatch-times').value;
     var arrivalTimeFrame = parseFloat(document.getElementById("hdn-WOArrivalTimeFrame-id").value).toFixed(2);
     var scheduledDate = document.getElementById("ScheduledDate").value;
     var scheduledTime = document.getElementById("ddl-dispatch-scheduled-times").value;
     var dateErrorSpan = document.getElementById("ScheduledDate-Error");  
     var timeErrorSpan = document.getElementById("ScheduledTime-Error");;

     var resultdata =  $.get('/WorkOrderDispatch/GetScheduledEndDate', {
         dispStartDate: startDate, dispStartTime: startTime, dispTimeFrame: arrivalTimeFrame,
         dispScheduledDate: scheduledDate, dispScheduledTime: scheduledTime
     }).done(function (result) {
         
         if (result == 'hasDaysDifference') {
             timeErrorSpan.textContent = '';
             dateErrorSpan.textContent = 'Enter the Scheduled Date within the arrival time frame ' + arrivalTimeFrame + ' Hrs'
             $wizard.wizard('changeTo', '#' + tabPaneNames.general);
             return false;
         }
         else if (result == 'hasTimeDifference')
         {
             dateErrorSpan.textContent = '';
             timeErrorSpan.textContent = 'Enter the Scheduled Date within the arrival time frame ' + arrivalTimeFrame + ' Hrs'  
             $wizard.wizard('changeTo', '#' + tabPaneNames.general);
             return false;
         }
         else {
             dateErrorSpan.textContent = '';
             timeErrorSpan.textContent = '';
            
             return true;
         }
     });           
     return resultdata;
    
 }

// Code in MVC controller

 public async Task<JsonResult> GetScheduledEndDate(string dispStartDate, string dispStartTime, string dispTimeFrame, string dispScheduledDate, string dispScheduledTime)        {

     var UserID = User.Identity.GetUserId();
     var loginUser = await DbContext.Employees.Where(x => x.ApplicationUserID == UserID).FirstOrDefaultAsync(); 

     if (loginUser == null)
     {
         throw new OfficetraxException(ErrorCode.NotFound);
     }            
     TimeZoneInfo employeeTimeZone = TimeZoneTools.FindTimeZone(loginUser.TimeZone);
     DateTime now = DateTime.UtcNow;
     string DispatchNowString = "[Dispatch Now]";
     DateTime startDate = Convert.ToDateTime(dispStartDate);
    
     DateTime scheduledDate;
     DateTime? dispatchScheduledDate = null;

     if (!string.IsNullOrEmpty(dispScheduledDate))
     {
           scheduledDate = Convert.ToDateTime(dispScheduledDate);
           dispatchScheduledDate = scheduledDate.ApplyTimeAndTimeZone(dispScheduledTime, employeeTimeZone);
     }

     double? arrivalTimeFrame = Convert.ToDouble(dispTimeFrame);
     string combinedscheduleDate = dispScheduledDate + " " + dispScheduledTime;
     
     DateTime dispatchStartDate = dispStartTime == DispatchNowString ? now : startDate.ApplyTimeAndTimeZone(dispStartTime, employeeTimeZone); 

     DateTime? scheduledEndDate = arrivalTimeFrame.HasValue ?
                                        dispatchStartDate.AddHours(arrivalTimeFrame.Value) : (DateTime?)null;

     

     //DateTime? dispatchScheduledDate = DateTime.Parse(combinedscheduleDate); 

     if (scheduledEndDate.HasValue && dispatchScheduledDate.HasValue)
     {
         if(dispatchScheduledDate < dispatchStartDate)
         {
             if (dispatchScheduledDate.Value.Date == dispatchStartDate.Date)
             {
                 return Json("hasTimeDifference", JsonRequestBehavior.AllowGet);
             }
             else
             {
                 return Json("hasDaysDifference", JsonRequestBehavior.AllowGet);
             }
         }
         if(dispatchScheduledDate > scheduledEndDate)
         {
             if(dispatchScheduledDate.Value.Date == scheduledEndDate.Value.Date)
             {
                 return Json("hasTimeDifference", JsonRequestBehavior.AllowGet);
             }
             else
             {
                 return Json("hasDaysDifference", JsonRequestBehavior.AllowGet);
             }
             
         }
         else
         {
             return Json("noDifference", JsonRequestBehavior.AllowGet);
         }
     }
     return Json("noDifference", JsonRequestBehavior.AllowGet);

     
 }

JSON.stringify omits properties from object

I am trying to understand why JSON.stringify shows a different output to the object I am expecting to see.

In my case, my object has a property of height and width

So, if I were to do perform the following

const canvas = new fabric.Canvas("c");
console.log("canvas.width: " + canvas.width)

Then the output would be

canvas.width: 300

However, when I perform

console.log(JSON.stringify(canvas));

the output does not include the width.

In my real situation, I am using fabricjs.com

JSFiddle: https://jsfiddle.net/tdge2908/2/

<canvas id="c"></canvas>  
<div id="result">
</div>

const canvas = new fabric.Canvas("c");
console.log("canvas.isRendering: " + canvas.width)
const result= document.getElementById("result");
result.innerText = JSON.stringify(canvas);

Likewise, I could add something to my canvas object, and it still won’t show when I stringify it.

EG

const canvas = new fabric.Canvas("c");
canvas.myMadeUpThing = "hello";
console.log("canvas.my made up thing: " + canvas.myMadeUpThing ); //this works
const result= document.getElementById("result");
result.innerText = JSON.stringify(canvas);

JSFiddle: https://jsfiddle.net/tdge2908/4/

Why does calling JSON.stringify on this object seem to be doing something unexpected?

How to avoid main menu to slow loading on mobile

When I open my website on mobile it waits until all the content is loaded to show my main menu toggle button. I don’t know why that’s happening, it’s quite awful to see the navbar without showing the menu.

I’ve tried several things to avoid that but they don’t work. I also want to prevent for the menu to overlap my content on mobile when it’s unfolded, I think the better option is to push the content down when the menu is opened (I’m not sure if it’s the better practice).
My github repo is here: https://github.com/leosenderovsky/mi-sitio.

Issue with Smooth Scrolling: Forward Scrolling Works, Backward Scrolling Doesn’t on Mobile

I’m implementing smooth scrolling functionality on my webpage. When a category button is clicked, the page scrolls to the corresponding section smoothly. This works perfectly on desktop browsers and for forward scrolling on mobile devices, but it fails to scroll backward correctly on mobile devices. Here is the relevant part of my code:

window.addEventListener("click", (event) => {
    const categoryButton = event.target.classList.contains("cmp-css-category");
    if (categoryButton) {
        event.preventDefault(); 
        const targetId = event.target.getAttribute('href').slice(1); 
        const targetCard = document.getElementById(targetId);
        if (targetCard) {
            const rect = targetCard.getBoundingClientRect();
            const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
            const scrollPosition = rect.top + scrollTop;
            window.scrollTo({
                top: scrollPosition,
                behavior: 'smooth'
            });
        }
    }
});

Problem Description

Forward Scrolling: When clicking on a category button to scroll down to a section, it works as expected.
Backward Scrolling: When clicking on a category button to scroll back up to a previous section, the scroll behavior is inconsistent and doesn’t scroll to the correct position. This issue is specifically on mobile devices.

Verified Scroll Position Calculation:

const rect = targetCard.getBoundingClientRect();
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
const scrollPosition = rect.top + scrollTop;

window.scrollTo({
    top: scrollPosition,
    behavior: 'smooth'
});

Checked Consistency Across Devices: Tested the code on desktop browsers (Chrome, Firefox, Safari) where it works fine.

What Were You Expecting?
I expected the smooth scrolling functionality to work consistently on both desktop and mobile devices, allowing the page to scroll smoothly to the target section regardless of the direction (both forward and backward scrolling).

new error_1.MongoTopologyClosedError());

I am creating a card website and I have an absurd problem. This comes from the server side of two functions: one that I use to update the user’s credits on the homepage and the other to display new packs that an admin has added, also on the homepage.


app.post('/set_admin_pack', async function(req,res){

    const packs = req.body;
    const pwmClient = await client.connect();
    await pwmClient.db("PWM").collection("AdminPacks").insertOne({name: packs.name, cost: packs.cost, imgpath: packs.imgpath, rarity:packs.rarity});
    res.send(packs);
    await client.close();

})

app.get('/get_admin_packs', async function(req,res){

    const pwmClient = await client.connect();
    const adm_packs = await pwmClient.db("PWM").collection("AdminPacks").find().toArray();
    console.log(adm_packs);
    res.status(200).send(adm_packs);
    await client.close();

})

app.post('/set_credits', async function(req, res){

    const user = req.body;
    console.log(user);
    const pwmClient = await client.connect();
    let userFound = await pwmClient.db("PWM").collection("Users").findOne({nome: user.name, password: user.password});
    
    if(!userFound.credits)
        await pwmClient.db("PWM").collection("Users").updateOne({_id:userFound.id}, {$set: {credits: 1000}});

    res.status(201).json({id: userFound._id, credits: userFound.credits});
    await client.close();

})

app.post('/get_credits', async function(req, res){

    const user = req.body.id;
    let objid = new ObjectId(user);
    const pwmClient = await client.connect();
    let userFound = await pwmClient.db("PWM").collection("Users").findOne({_id: objid});
    res.status(200).json({_id: objid, credits: userFound.credits});
    await client.close();

})

These are the functions that do not work, or rather, when I comment out the first two, the server-side functions that manage credits work correctly:


/*app.post('/set_admin_pack', async function(req,res){

    const packs = req.body;
    const pwmClient = await client.connect();
    await pwmClient.db("PWM").collection("AdminPacks").insertOne({name: packs.name, cost: packs.cost, imgpath: packs.imgpath, rarity:packs.rarity});
    res.send(packs);
    await client.close();

})

app.get('/get_admin_packs', async function(req,res){

    const pwmClient = await client.connect();
    const adm_packs = await pwmClient.db("PWM").collection("AdminPacks").find().toArray();
    console.log(adm_packs);
    res.status(200).send(adm_packs);
    await client.close();

})*/


app.post('/set_credits', async function(req, res){

    const user = req.body;
    console.log(user);
    const pwmClient = await client.connect();
    let userFound = await pwmClient.db("PWM").collection("Users").findOne({nome: user.name, password: user.password});
    
    if(!userFound.credits)
        await pwmClient.db("PWM").collection("Users").updateOne({_id:userFound.id}, {$set: {credits: 1000}});

    res.status(201).json({id: userFound._id, credits: userFound.credits});
    await client.close();

})

app.post('/get_credits', async function(req, res){

    const user = req.body.id;
    let objid = new ObjectId(user);
    const pwmClient = await client.connect();
    let userFound = await pwmClient.db("PWM").collection("Users").findOne({_id: objid});
    res.status(200).json({_id: objid, credits: userFound.credits});
    await client.close();

})

However, when I comment out the last two, the first two POST functions work correctly:

app.post('/set_admin_pack', async function(req,res){

    const packs = req.body;
    const pwmClient = await client.connect();
    await pwmClient.db("PWM").collection("AdminPacks").insertOne({name: packs.name, cost: packs.cost, imgpath: packs.imgpath, rarity:packs.rarity});
    res.send(packs);
    await client.close();

})

app.get('/get_admin_packs', async function(req,res){

    const pwmClient = await client.connect();
    const adm_packs = await pwmClient.db("PWM").collection("AdminPacks").find().toArray();
    console.log(adm_packs);
    res.status(200).send(adm_packs);
    await client.close();

})



/*app.post('/set_credits', async function(req, res){

    const user = req.body;
    console.log(user);
    const pwmClient = await client.connect();
    let userFound = await pwmClient.db("PWM").collection("Users").findOne({nome: user.name, password: user.password});
    
    if(!userFound.credits)
        await pwmClient.db("PWM").collection("Users").updateOne({_id:userFound.id}, {$set: {credits: 1000}});

    res.status(201).json({id: userFound._id, credits: userFound.credits});
    await client.close();

})

app.post('/get_credits', async function(req, res){

    const user = req.body.id;
    let objid = new ObjectId(user);
    const pwmClient = await client.connect();
    let userFound = await pwmClient.db("PWM").collection("Users").findOne({_id: objid});
    res.status(200).json({_id: objid, credits: userFound.credits});
    await client.close();

})*/

When none are commented out and I load the homepage, the server crashes with the following error:

C:UsersuserOneDriveDesktopnode jsexpressnode_modulesmongodblibsdamtopology.js:538
        drainWaitQueue(topology[kWaitQueue], new error_1.MongoTopologyClosedError());
                                             ^

MongoTopologyClosedError: Topology is closed
    at processWaitQueue (C:UsersuserOneDriveDesktopnode jsexpressnode_modulesmongodblibsdamtopology.js:538:46)
    at Topology.selectServer (C:UsersuserOneDriveDesktopnode jsexpressnode_modulesmongodblibsdamtopology.js:294:9)
    at retryOperation (C:UsersuserOneDriveDesktopnode jsexpressnode_modulesmongodbliboperationsexecute_operation.js:187:35)
    at executeOperation (C:UsersuserOneDriveDesktopnode jsexpressnode_modulesmongodbliboperationsexecute_operation.js:140:26)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async FindCursor._initialize (C:UsersuserOneDriveDesktopnode jsexpressnode_modulesmongodblibcursorfind_cursor.js:51:26)
    at async FindCursor.cursorInit (C:UsersuserOneDriveDesktopnode jsexpressnode_modulesmongodblibcursorabstract_cursor.js:471:27)
    at async FindCursor.fetchBatch (C:UsersuserOneDriveDesktopnode jsexpressnode_modulesmongodblibcursorabstract_cursor.js:503:13)
    at async FindCursor.next (C:UsersuserOneDriveDesktopnode jsexpressnode_modulesmongodblibcursorabstract_cursor.js:228:13)
    at async [Symbol.asyncIterator] (C:UsersuserOneDriveDesktopnode jsexpressnode_modulesmongodblibcursorabstract_cursor.js:159:34) {
  [Symbol(errorLabels)]: Set(0) {}
}

Honestly, I don’t know how to solve the problem. I am a beginner in web programming and need help.

I can’t complain why when the code doesn’t work correctly

Google Street View API

I’m trying to make use of the googlemaps api, but i’m having a problem.

Initializing the streetviewmap like this will also publish the coordonates of the location into client side.
Making use of the panorama id instead of using the streetview is showing to the client the panorama id.

Both of these cases shows the user the coordonates/panorama id which is not a good approach for my project. Is there a way i can serve the streetview location choosen to the users but to not display anywhere the location of it ?

function initializeStreetView(latitude, longitude) {
    var minimapContainer = document.getElementById("minimap");

    // Initialize the Street View map
    panorama = new google.maps.StreetViewPanorama(
        streetViewContainer, {
        position: { lat: parseFloat(latitude - {{ $randomAdditionLatitude }}), lng: parseFloat(longitude - {{ $randomAdditionLongitude }}) },
        pov: { heading: 165, pitch: 0 },
        disableDefaultUI: true,  // Disable all default UI controls
        zoom: 1,
        clickToGo: false,
        panControl: false,
        disableDoubleClickZoom: true,
        keyboardShortcuts: false,
        linksControl: false,  // Disable links control
        addressControl: false, // Hide address control
        fullscreenControl: false, // Hide fullscreen control
        showRoadLabels: false, // Hide road labels
        motionTracking: false, // Disable motion tracking
        motionTrackingControl: false // Disable motion tracking control
    }
    );
document.addEventListener("DOMContentLoaded", function () {
    initializeStreetView('{{ $contest->latitude }}', '{{ $contest->longitude }}');

Thank you!

I’ve tried to crypt the coordonates on server, but the decrypt must happen on the client side therefore the coordonates still visible on client side.

Autoplay HTML video if url hash is present

I wrote some javascript to detect if a specific URL hash is present to automatically play a specific video when the page loads.

I am able to determine that the video play code is being activated via the togglevid() alert when the page loads. However, the video never starts playing.

Can you take a look at the code below and see what I am missing here?

if (window.location.hash) {
  // if "playvideo" hash is present, automatically start playing the video
  var runvid = document.getElementById(window.location.hash.slice(1)).getElementsByTagName('video').item(0);
  togglevid(runvid);
}

// Create listener for each video to play when clicked on
var vids = document.getElementsByTagName('video')
for (var i = 0; i < vids.length; i++) {
  var x = vids.item(i);
  vids.item(i).addEventListener("click", function() {
    togglevid(this);
  });
}

function togglevid(x) {
  alert("Video toggle triggered.  SRC: " + x.src);
  if (x.paused == true) x.play();
  else x.pause();
}
body {
  max-width: 800px;
}

video {
  max-width: 800px;
}
<h1>TEST</h1>
<p>Click on video to start playing if it hasn't already started.</p>
<div id="playvideo">
  <video src="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"></video>
</div>

Is shapes.devs deprecated in jointjs v4.0.4?

I am currently trying to get familiar with a JS library – JointJS(to upgrade a project from version 3.7.7 to 4.0.4 because it is now dependency-free). Apparently I do not see documentation for the free version as much as for JointJS plus.

Is shapes.devs deprecated?
According to the code I still see shapes.devs but the changelog says it is removed?

https://github.com/clientIO/joint/blob/v4.0.4/packages/joint-core/types/joint.d.ts

https://changelog.jointjs.com/plus/4.0.0/changelog.html
(Also this seems to be for plus version could not find changelogs for open source)

Can someone also provide suggestions on how can I upgrade it efficiently while getting familiar to the new library and the way it’s built in the project I am working on(it is an Angular project).

How do i handle interpolated Animated and dot indicator gracefully while I have a copy of data list?

I want to create a bidirectional swiper my own, but I have a problem about to seek a way how do i handle the interpolated. here’s my swiper so far

Swiper.js

import React, {useCallback, useRef} from 'react';
import {Animated, View} from 'react-native';

const Swiper = ({
  RenderItem = () => null,
  data = [],
  RenderDotIndicator = false,
  containerWidth = 0,
}) => {
  const refAnimated = useRef(new Animated.Value(0)).current;
  // here I copy the data that I got from props
  // so if the data is [1,2] it would be [1,2,1,2]
  const [InternalData, setInternalData] = React.useState([...data, ...data]);

  // here I want to handle that interpolated only used 2 length instead of 4
  const interpolateFunct = (outputRange, index) =>
    refAnimated.interpolate({
      inputRange: [
        (index - 1) * width,
        index * width,
        (index + 1) * width,
      ],
      outputRange,
      extrapolate: 'clamp',
    });

  const WrappedRenderItem = useCallback(
    ({item, index}) => (
      <View style={{overflow: 'hidden', width: width}}>
        {RenderItem({item, index})}
      </View>
    ),
    [],
  );

  const WrappedRenderDotIndicator = useCallback(() => {
    const dotItem = data.map((item, index) => {
      return (
        <Animated.View
          key={'dot' + item + index.toString()}
          style={{
            width: 6,
            backgroundColor: '#D3D3D3',
            height: 6,
            borderRadius: 6 / 2,
            marginHorizontal: 5,
            transform: [{scale: interpolateFunct([1, 2, 1], index)}],
          }}
        />
      );
    });
    return (
      <View
        style={{
          flexDirection: 'row',
          alignSelf: 'center',
          position: 'absolute',
          bottom: 6,
        }}
      >
        {dotItem}
      </View>
    );
  }, [RenderDotIndicator]);

  return (
    <View>
      <Animated.FlatList
        ref={refAnimated}
        data={InternalData}
        renderItem={WrappedRenderItem}
        horizontal
        pagingEnabled
        onScroll={Animated.event(
          [{nativeEvent: {contentOffset: {x: refAnimated}}}],
          {useNativeDriver: true},
        )}
      />
      <WrappedRenderDotIndicator />
    </View>
  );
};

Swiper.displayName = 'Swiper';

export default Swiper;

currently, using the code above, I got this behaviour (notice the dot indicator when I sliding from 2nd to 3rd image, the dot is not reflecting the first one)

https://jmp.sh/JeFQ2CbF (or run snippet below)

<div style="position: relative; padding-bottom: 56.25%; height: 0;"><iframe src="https://jumpshare.com/embed/IFu1Zeev0hccyrbvqm9h" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"></iframe></div>

How do I handle when sliding from 2nd to 3rd, the dot indicator reflecting the first one?

[ERR_HTTP_HEADERS_SENT]: Cannot append headers after they are sent to the client on middleware.js during authentication

I have a project where I do authentication checking on middleware.js file. It was doing fine locally and on development server, but when we deploy it to production it got:

[ERR_HTTP_HEADERS_SENT]: Cannot append headers after they are sent to the client
import { NextResponse } from 'next/server'
import { getBackendUrl } from './components/Constanta/Constanta'

// This function can be marked `async` if using `await` inside
export async function middleware(request) {
    const BE_URL = getBackendUrl('general')
    const token = request.cookies.get('token')
    if(token) {
        try {
            const response = await fetch(BE_URL+"check-auth/", {
                method: "GET",
                headers: {
                    'Authorization': `Bearer ${token.value}`,
                    "Content-Type": "application/json",
                },
            })
            if (!response.ok) {
                const resp = NextResponse.redirect(new URL('/login', request.url))
                resp.cookies.set("route", new URL(request.url).pathname);
                resp.cookies.set("token", null);
                resp.cookies.set("userID", null);
                resp.cookies.set("roleID", null);
                return resp
            } else {
                return NextResponse.next();
            }
        }
        catch (error) {
            console.log(error)
            const resp = NextResponse.redirect(new URL('/login', request.url));
            resp.cookies.set("route", new URL(request.url).pathname);
            return resp;    
        }
    } else {
        const resp = NextResponse.redirect(new URL('/login', request.url));
        resp.cookies.set("route", new URL(request.url).pathname);
        return resp;   
    }
}

 
// See "Matching Paths" below to learn more
export const config = {
    matcher: [
        '/',
        ...
    ],
}

Did I do something wrong? The production server should be mirroring the development server and I built it on Docker so I got confused here.

Create unique key/hash based on object

Say I have the following JavaScript objects:

const obj1 = {
 key1: 'str1',
 key2: 'str2'
}

const obj2 = {
 key2: 'str2',
 key1: 'str1'
}

const obj3 = {
 key1: 'something else',
 key2: 'str2'
}

const obj4 = {
 differentKey: 'str1',
 key2: 'str2'
}

I’d like to create a unique key based on a given object. This is so I can properly cache some data related to each object. In this scenario, obj1 and obj2 should have the same key, as the only difference is the ordering of properties. obj3 and obj4 should have different keys from each other. I tried using JSON.stringify() but this gives different results for obj1 and obj2 due to the ordering. Is there a way to get around this, ideally that can work with non-primitive types?

How to resolve that after searching request a property name has changed to a property id?

I am using a React Native Expo web app for the frontend and Django for the backend.

I have a search function that works fine. But the problem I am facing is that after a search term the property name of a specific animal has changed to a property id (number).

What I mean with this is that in the accordion the category name is shown. But after the search the category id is displayed.

In the frontend I have an accordion with some properties. The property for category looks:

export const AccordionItemsProvider = ({ children }) => {   
    const [categoryExpanded, setCategory] = useState(false);
    

    const accordionItems = (item) => {
        return (
            <>
            
                <List.Accordion
                    title="Familie"
                    expanded={categoryExpanded}
                    onPress={() => setCategory(!categoryExpanded)}>
                    <Text>{item.category}</Text>
                </List.Accordion>
                
            </>
        );
    };

    return (
        <AccordionItemsContext.Provider
            value={{
                accordionItems,
            }}>
            {children}
        </AccordionItemsContext.Provider>
    );
};

So the name of category will be displayed. But after the search the id of category will be displayd. And not the name.

The search context of animal looks:

/* eslint-disable prettier/prettier */

import React, { createContext, useEffect, useState } from "react";

import { fetchAnimalData } from "./animal/animal.service";
import useDebounce from "../hooks/use-debounce";

export const SearchAnimalContext = createContext();
export const SearchAnimalContextProvider = ({ children }) => {
    const [searchAnimal, setSearchAnimal] = useState([]);
    const [results, setResults] = useState([]);
    const [loading, setLoading] = useState(false);
    const [error, setError] = useState(null);
    const [input, setInput] = useState("");
    const debounce = useDebounce(input, 500);

    useEffect(() => {
        if (debounce === "") {
            setResults([]);
            return;
        }
        fetchAnimalData(debounce)
            .then((response) => {
                setResults(response);
            })
            .catch((err) => {
                setError(err);
            });

        fetchAnimalData();
    }, [debounce]);

    const performSearch = async (text) => {
        if (text.trim() === "") {
            setResults([]);
        }
        setLoading(true);
        setError(null);
        setTimeout(() => {
            fetchAnimalData(text)
                .then((response2) => {
                    setResults(response2);
                    console.log(response2);

                    setLoading(false);
                })
                .catch((err) => {
                    setLoading(false);
                    setError(err);
                });
        }, 100);
    };
    return (
        <SearchAnimalContext.Provider
            value={{
                results,
                setResults,
                searchAnimal,
                setSearchAnimal,
                input,
                setInput,
                performSearch,
                loading,
                error,
            }}>
            {children}
        </SearchAnimalContext.Provider>
    );
};

And the output after a search request of the console.log looks:

category
: 
30
category_name
: 
"Katachtigen - Felidae"

So before the search category is displayed correctly: “Katachtigen – Felidae”. But after the search category is displayed as 30 – category_id: which is not correct.

And the seach function in the component looks:

import React, { useContext, useEffect, useState } from "react";
import { SafeArea } from "../../../components/utility/safe-area.component";
import { SearchAnimalContext } from "../../../services/search-animal.context";
import { fetchSubCategoryData } from "../../../services/category/category.service";

export const SubCategoryScreen = ({ route, navigation }) => {
    
    const [isLoading, setLoading] = useState(true);
    const { performSearch, results, setInput, input } = useContext(SearchAnimalContext);    
    const [isSearchbarFocused, setSearchbarFocused] = useState(false);  

    useEffect(() => {
        fetchSubCategoryData(route.params.subcategories).then((data) => {
            setSubCategoryList(data.animals.length > 0 ? data.animals : data.subcategories);
            setLoading(false);
        });
    }, [route]);

    const handleSearchChange = (text) => {
        setInput(text);
        if (text.length === 0) {
            performSearch(""); 
            navigation.navigate("dieren");
        } else {
            performSearch(text);
        }
    };



    return (
        <SafeArea>
            {isLoading && (
                <LoadingContainer>
                    <ActivityIndicator animating={true} color={MD2Colors.green200} />
                </LoadingContainer>
            )}
            <Searchbar
                placeholder="Search animals"
                value={input}
                onFocus={() => setSearchbarFocused(true)}
                onChangeText={handleSearchChange}
                onBlur={() => setSearchbarFocused(false)}
                style={styles.searchbar}
            />
            
        </SafeArea>
    );
};

And the model animal from the backend looks:

import sys
from io import BytesIO
from django.db import models

class Animal(models.Model):   
    name = models.CharField(max_length=100, verbose_name="Naam")
    sort = models.CharField(max_length=100, default='',  
    category = models.ForeignKey(
        Category, related_name='animals', on_delete=models.CASCADE, verbose_name="Familie")   

    def category_name(self):
        return self.category.name
   

    class Meta:
        verbose_name = "Dier"
        verbose_name_plural = "Dieren"
        # permissions = [("set_display_flag", "Check name is display or not",)]

   
        super(Animal, self).save()

    def __str__(self):
        return self.name

How to display the correct category name and not the category id after a search request?