javascript json object value returns undefined

I realize there are 100’s of posts about javascript json objects. And all of them imply my code should work, so I am sure I am missing something really stupid. Every attempt to access the json object’s key value results in undefined even though the json.parse works fine.

var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() {
         if (this.readyState == 4 && this.status == 200) {
            var resp = JSON.parse(this.responseText);
            alert(this.responseText);
            alert(resp.toString());
            alert(resp.exists);
            alert(resp['exists']);
            
         }
    };

This results in the following for alerts:

"{"exists":"True"}"
{"exists":"True"}
undefined
undefined

What incredibly obvious and dumb thing am I missing? I even attempted to use my exact string in w3schools example and it appears to work fine
https://www.w3schools.com/js/tryit.asp?filename=tryjson_object_dot

Thank you in advance.

Module not found: Error: Package path . is not exported from package D:CWS-websitenode_modulesfirebase. This is the error I am getting . please

Module not found: Error: Package path . is not exported from package D:CWS-websitenode_modulesfirebase (see exports field in D:CWS-websitenode_modulesfirebasepackage.json)

This is the error BUT I am imported firebase


var firebaseApp = firebase.initializeApp({
// MY CREDENTIALS ...
});

var db = firebaseApp.firestore();

export { db };

Vue: Class/Component Inheritance

Apologies if this has been posted in some other variation before, but I can’t seem to find a good thread on how to do it in my use case. I’m getting tripped up on how to make Vue more OOP based (more importantly how to inherit from other components). I’m attempting to use Composition API, as it seems more like a flexible option, but maybe I’m missing how to properly leverage it.

I have a base component called FieldText. This sets up the initial template and boilerplate code for all of my other Field* components (Number, Checkbox, etc.) and allows for adding in custom attributes to the input element, like the input type, and validation rules that only apply to the Field* component… like min and max only work for number and date like fields, so I’d only like to contain this logic to those components.

Then I have FieldNumber, which attempts to “extend” from FieldText by using it as the template. The problem here is that when I do the v-bind="$props", it’s not actually going to the input element… it’s going to the parent div. You can solve this by setting inheritAttrs: false on FieldText and doing a v-bind on the input el, but then I won’t have classes go to the parent element.

I could use Pug, but this looks like it comes with its own quirks, and I’m not sure it’d truly solve my issue. I also could try to abstract this out to composables, but that only solves the logical aspect, not the markup aspect.

I’m playing around with the idea of passing some sort of inputAttrs to FieldText, but the setup methods don’t interact. Now I’ve come to the conclusion that I’m not using Composition API properly, and I don’t know how I’d refactor this to behave in a more OOP fashion. Can someone provide some insight as to how I would approach this?

How to use methods of classes in Angular export function

I’d like to use a method in a export function defined in a class file.

export function MSALInstanceFactory(): IPublicClientApplication {
    return new PublicClientApplication({
        auth: AzureService.getConfiguration(), <-------- Compilation Error
        cache: {
            cacheLocation: BrowserCacheLocation.LocalStorage,
            storeAuthStateInCookie: isIE, // set to true for IE 11. Remove this line to use Angular Universal
        }
    });
}

export class AzureModule { }

This is the Service Class

@Injectable()
export class AzureService {

    constructor(private identityManagerApiRestService: IdentityManagerApiRestService) { }

    getConfiguration(): BrowserAuthOptions {
        let options: BrowserAuthOptions;
        this.identityManagerApiRestService.getAuthenticationConfiguration().subscribe(response =>{
            options.clientId = response.authenticationConfiguration.clientId;
            options.authority = response.authenticationConfiguration.authority;
            options.redirectUri = response.authenticationConfiguration.redirectUri;
        });
        return options;
    }
}

How can I use AzureService.getConfiguration() method in the exported function method in the Module. I want this because the values are dynamic and they are obtained in a rest call.

Facing an error while using onkeydown event

I have a code which I want to run on a code tag every time user changes it. I know that I could use onchange event but that only takes place after user has edited the content of an element and then click anywhere out of it. But my requirement is to run the function simultaneously. I tried onkeydown event but I am a facing error with it and I cant seem to figure out the issue. The code is below, pls help me. And by the way sorry the code is pretty long and I cant cut it short as I dont really understand the code as its copied from somewhere.

synataxHighlight(document.getElementById("myDiv"));

function synataxHighlight(elmnt, mode) {
  var lang = (mode || "html");
  var elmntObj = (document.getElementById(elmnt) || elmnt);
  var elmntTxt = elmntObj.innerHTML;
  var tagcolor = "mediumblue";
  var tagnamecolor = "brown";
  var attributecolor = "red";
  var attributevaluecolor = "mediumblue";
  var commentcolor = "green";
  var cssselectorcolor = "brown";
  var csspropertycolor = "red";
  var csspropertyvaluecolor = "mediumblue";
  var cssdelimitercolor = "black";
  var cssimportantcolor = "red";  
  var jscolor = "black";
  var jskeywordcolor = "mediumblue";
  var jsstringcolor = "brown";
  var jsnumbercolor = "red";
  var jspropertycolor = "black";
  elmntObj.style.fontFamily = "Consolas,'Courier New', monospace";
  if (!lang) {lang = "html"; }
  if (lang == "html") {elmntTxt = htmlMode(elmntTxt);}
  if (lang == "css") {elmntTxt = cssMode(elmntTxt);}
  if (lang == "js") {elmntTxt = jsMode(elmntTxt);}
  elmntObj.innerHTML = elmntTxt;

  function extract(str, start, end, func, repl) {
    var s, e, d = "", a = [];
    while (str.search(start) > -1) {
      s = str.search(start);
      e = str.indexOf(end, s);
      if (e == -1) {e = str.length;}
      if (repl) {
        a.push(func(str.substring(s, e + (end.length))));      
        str = str.substring(0, s) + repl + str.substr(e + (end.length));
      } else {
        d += str.substring(0, s);
        d += func(str.substring(s, e + (end.length)));
        str = str.substr(e + (end.length));
      }
    }
    this.rest = d + str;
    this.arr = a;
  }
  function htmlMode(txt) {
    var rest = txt, done = "", php, comment, angular, startpos, endpos, note, i;
    comment = new extract(rest, "&lt;!--", "--&gt;", commentMode, "W3HTMLCOMMENTPOS");
    rest = comment.rest;
    while (rest.indexOf("&lt;") > -1) {
      note = "";
      startpos = rest.indexOf("&lt;");
      if (rest.substr(startpos, 9).toUpperCase() == "&LT;STYLE") {note = "css";}
      if (rest.substr(startpos, 10).toUpperCase() == "&LT;SCRIPT") {note = "javascript";}        
      endpos = rest.indexOf("&gt;", startpos);
      if (endpos == -1) {endpos = rest.length;}
      done += rest.substring(0, startpos);
      done += tagMode(rest.substring(startpos, endpos + 4));
      rest = rest.substr(endpos + 4);
      if (note == "css") {
        endpos = rest.indexOf("&lt;/style&gt;");
        if (endpos > -1) {
          done += cssMode(rest.substring(0, endpos));
          rest = rest.substr(endpos);
        }
      }
      if (note == "javascript") {
        endpos = rest.indexOf("&lt;/script&gt;");
        if (endpos > -1) {
          done += jsMode(rest.substring(0, endpos));
          rest = rest.substr(endpos);
        }
      }
    }
    rest = done + rest;
    for (i = 0; i < comment.arr.length; i++) {
        rest = rest.replace("W3HTMLCOMMENTPOS", comment.arr[i]);
    }
    return rest;
  }
  function tagMode(txt) {
    var rest = txt, done = "", startpos, endpos, result;
    while (rest.search(/(s|<br>)/) > -1) {    
      startpos = rest.search(/(s|<br>)/);
      endpos = rest.indexOf("&gt;");
      if (endpos == -1) {endpos = rest.length;}
      done += rest.substring(0, startpos);
      done += attributeMode(rest.substring(startpos, endpos));
      rest = rest.substr(endpos);
    }
    result = done + rest;
    result = "<span style=color:" + tagcolor + ">&lt;</span>" + result.substring(4);
    if (result.substr(result.length - 4, 4) == "&gt;") {
      result = result.substring(0, result.length - 4) + "<span style=color:" + tagcolor + ">&gt;</span>";
    }
    return "<span style=color:" + tagnamecolor + ">" + result + "</span>";
  }
  function attributeMode(txt) {
    var rest = txt, done = "", startpos, endpos, singlefnuttpos, doublefnuttpos, spacepos;
    while (rest.indexOf("=") > -1) {
      endpos = -1;
      startpos = rest.indexOf("=");
      singlefnuttpos = rest.indexOf("'", startpos);
      doublefnuttpos = rest.indexOf('"', startpos);
      spacepos = rest.indexOf(" ", startpos + 2);
      if (spacepos > -1 && (spacepos < singlefnuttpos || singlefnuttpos == -1) && (spacepos < doublefnuttpos || doublefnuttpos == -1)) {
        endpos = rest.indexOf(" ", startpos);      
      } else if (doublefnuttpos > -1 && (doublefnuttpos < singlefnuttpos || singlefnuttpos == -1) && (doublefnuttpos < spacepos || spacepos == -1)) {
        endpos = rest.indexOf('"', rest.indexOf('"', startpos) + 1);
      } else if (singlefnuttpos > -1 && (singlefnuttpos < doublefnuttpos || doublefnuttpos == -1) && (singlefnuttpos < spacepos || spacepos == -1)) {
        endpos = rest.indexOf("'", rest.indexOf("'", startpos) + 1);
      }
      if (!endpos || endpos == -1 || endpos < startpos) {endpos = rest.length;}
      done += rest.substring(0, startpos);
      done += attributeValueMode(rest.substring(startpos, endpos + 1));
      rest = rest.substr(endpos + 1);
    }
    return "<span style=color:" + attributecolor + ">" + done + rest + "</span>";
  }
  function attributeValueMode(txt) {
    return "<span style=color:" + attributevaluecolor + ">" + txt + "</span>";
  }
  function commentMode(txt) {
    return "<span style=color:" + commentcolor + ">" + txt + "</span>";
  }
  function cssMode(txt) {
    var rest = txt, done = "", s, e, comment, i, midz, c, cc;
    comment = new extract(rest, //*/, "*/", commentMode, "W3CSSCOMMENTPOS");
    rest = comment.rest;
    while (rest.search("{") > -1) {
      s = rest.search("{");
      midz = rest.substr(s + 1);
      cc = 1;
      c = 0;
      for (i = 0; i < midz.length; i++) {
        if (midz.substr(i, 1) == "{") {cc++; c++}
        if (midz.substr(i, 1) == "}") {cc--;}
        if (cc == 0) {break;}
      }
      if (cc != 0) {c = 0;}
      e = s;
      for (i = 0; i <= c; i++) {
        e = rest.indexOf("}", e + 1);
      }
      if (e == -1) {e = rest.length;}
      done += rest.substring(0, s + 1);
      done += cssPropertyMode(rest.substring(s + 1, e));
      rest = rest.substr(e);
    }
    rest = done + rest;
    rest = rest.replace(/{/g, "<span style=color:" + cssdelimitercolor + ">{</span>");
    rest = rest.replace(/}/g, "<span style=color:" + cssdelimitercolor + ">}</span>");
    for (i = 0; i < comment.arr.length; i++) {
        rest = rest.replace("W3CSSCOMMENTPOS", comment.arr[i]);
    }
    return "<span style=color:" + cssselectorcolor + ">" + rest + "</span>";
  }
  function cssPropertyMode(txt) {
    var rest = txt, done = "", s, e, n, loop;
    if (rest.indexOf("{") > -1 ) { return cssMode(rest); }
    while (rest.search(":") > -1) {
      s = rest.search(":");
      loop = true;
      n = s;
      while (loop == true) {
        loop = false;
        e = rest.indexOf(";", n);
        if (rest.substring(e - 5, e + 1) == "&nbsp;") {
          loop = true;
          n = e + 1;
        }
      }
      if (e == -1) {e = rest.length;}
      done += rest.substring(0, s);
      done += cssPropertyValueMode(rest.substring(s, e + 1));
      rest = rest.substr(e + 1);
    }
    return "<span style=color:" + csspropertycolor + ">" + done + rest + "</span>";
  }
  function cssPropertyValueMode(txt) {
    var rest = txt, done = "", s;
    rest = "<span style=color:" + cssdelimitercolor + ">:</span>" + rest.substring(1);
    while (rest.search(/!important/i) > -1) {
      s = rest.search(/!important/i);
      done += rest.substring(0, s);
      done += cssImportantMode(rest.substring(s, s + 10));
      rest = rest.substr(s + 10);
    }
    result = done + rest;    
    if (result.substr(result.length - 1, 1) == ";" && result.substr(result.length - 6, 6) != "&nbsp;" && result.substr(result.length - 4, 4) != "&lt;" && result.substr(result.length - 4, 4) != "&gt;" && result.substr(result.length - 5, 5) != "&amp;") {
      result = result.substring(0, result.length - 1) + "<span style=color:" + cssdelimitercolor + ">;</span>";
    }
    return "<span style=color:" + csspropertyvaluecolor + ">" + result + "</span>";
  }
  function cssImportantMode(txt) {
    return "<span style=color:" + cssimportantcolor + ";font-weight:bold;>" + txt + "</span>";
  }
  function jsMode(txt) {
    var rest = txt, done = "", esc = [], i, cc, tt = "", sfnuttpos, dfnuttpos, compos, comlinepos, keywordpos, numpos, mypos, dotpos, y;
    for (i = 0; i < rest.length; i++)  {
      cc = rest.substr(i, 1);
      if (cc == "\") {
        esc.push(rest.substr(i, 2));
        cc = "W3JSESCAPE";
        i++;
      }
      tt += cc;
    }
    rest = tt;
    y = 1;
    while (y == 1) {
      sfnuttpos = getPos(rest, "'", "'", jsStringMode);
      dfnuttpos = getPos(rest, '"', '"', jsStringMode);
      compos = getPos(rest, //*/, "*/", commentMode);
      comlinepos = getPos(rest, ////, "<br>", commentMode);      
      numpos = getNumPos(rest, jsNumberMode);
      keywordpos = getKeywordPos("js", rest, jsKeywordMode);
      dotpos = getDotPos(rest, jsPropertyMode);
      if (Math.max(numpos[0], sfnuttpos[0], dfnuttpos[0], compos[0], comlinepos[0], keywordpos[0], dotpos[0]) == -1) {break;}
      mypos = getMinPos(numpos, sfnuttpos, dfnuttpos, compos, comlinepos, keywordpos, dotpos);
      if (mypos[0] == -1) {break;}
      if (mypos[0] > -1) {
        done += rest.substring(0, mypos[0]);
        done += mypos[2](rest.substring(mypos[0], mypos[1]));
        rest = rest.substr(mypos[1]);
      }
    }
    rest = done + rest;
    for (i = 0; i < esc.length; i++) {
      rest = rest.replace("W3JSESCAPE", esc[i]);
    }
    return "<span style=color:" + jscolor + ">" + rest + "</span>";
  }
  function jsStringMode(txt) {
    return "<span style=color:" + jsstringcolor + ">" + txt + "</span>";
  }
  function jsKeywordMode(txt) {
    return "<span style=color:" + jskeywordcolor + ">" + txt + "</span>";
  }
  function jsNumberMode(txt) {
    return "<span style=color:" + jsnumbercolor + ">" + txt + "</span>";
  }
  function jsPropertyMode(txt) {
    return "<span style=color:" + jspropertycolor + ">" + txt + "</span>";
  }
  function getDotPos(txt, func) {
    var x, i, j, s, e, arr = [".","<", " ", ";", "(", "+", ")", "[", "]", ",", "&", ":", "{", "}", "/" ,"-", "*", "|", "%"];
    s = txt.indexOf(".");
    if (s > -1) {
      x = txt.substr(s + 1);
      for (j = 0; j < x.length; j++) {
        cc = x[j];
        for (i = 0; i < arr.length; i++) {
          if (cc.indexOf(arr[i]) > -1) {
            e = j;
            return [s + 1, e + s + 1, func];
          }
        }
      }
    }
    return [-1, -1, func];
  }
  function getMinPos() {
    var i, arr = [];
    for (i = 0; i < arguments.length; i++) {
      if (arguments[i][0] > -1) {
        if (arr.length == 0 || arguments[i][0] < arr[0]) {arr = arguments[i];}
      }
    }
    if (arr.length == 0) {arr = arguments[i];}
    return arr;
  }
  function getKeywordPos(typ, txt, func) {
    var words, i, pos, rpos = -1, rpos2 = -1, patt;
    if (typ == "js") {
      words = ["abstract","arguments","boolean","break","byte","case","catch","char","class","const","continue","debugger","default","delete",
      "do","double","else","enum","eval","export","extends","false","final","finally","float","for","function","goto","if","implements","import",
      "in","instanceof","int","interface","let","long","NaN","native","new","null","package","private","protected","public","return","short","static",
      "super","switch","synchronized","this","throw","throws","transient","true","try","typeof","var","void","volatile","while","with","yield"];
    }
    for (i = 0; i < words.length; i++) {
      pos = txt.indexOf(words[i]);
      if (pos > -1) {
        patt = /W/g;
        if (txt.substr(pos + words[i].length,1).match(patt) && txt.substr(pos - 1,1).match(patt)) {
          if (pos > -1 && (rpos == -1 || pos < rpos)) {
            rpos = pos;
            rpos2 = rpos + words[i].length;
          }
        }
      } 
    }
    return [rpos, rpos2, func];
  }
  function getPos(txt, start, end, func) {
    var s, e;
    s = txt.search(start);
    e = txt.indexOf(end, s + (end.length));
    if (e == -1) {e = txt.length;}
    return [s, e + (end.length), func];
  }
  function getNumPos(txt, func) {
    var arr = ["<br>", " ", ";", "(", "+", ")", "[", "]", ",", "&", ":", "{", "}", "/" ,"-", "*", "|", "%", "="], i, j, c, startpos = 0, endpos, word;
    for (i = 0; i < txt.length; i++) {
      for (j = 0; j < arr.length; j++) {
        c = txt.substr(i, arr[j].length);
        if (c == arr[j]) {
          if (c == "-" && (txt.substr(i - 1, 1) == "e" || txt.substr(i - 1, 1) == "E")) {
            continue;
          }
          endpos = i;
          if (startpos < endpos) {
            word = txt.substring(startpos, endpos);
            if (!isNaN(word)) {return [startpos, endpos, func];}
          }
          i += arr[j].length;
          startpos = i;
          i -= 1;
          break;
        }
      }
    }  
    return [-1, -1, func];
  }  
}
<!DOCTYPE html>
<html>
<body>

<code id="myDiv" contenteditable onkeydown="synataxHighlight(document.getElementById('myDiv'));">
&lt;!DOCTYPE html&gt
&lt;html&gt
&lt;body&gt
&lt;h1&gt;Testing an HTML Syntax Highlighter&lt;/h2&gt
&lt;p&gt;Hello world!&lt;/p&gt
&lt;/body&gt;
&lt;/html&gt;
</code>
</body>
</html>

Toggling the color of a div box using JS

I’m trying to change the background color of this div box whenever it gets clicked. For some reason the funtcion only works whenever I click on the same div box twice. Am I missing something?

function selected_platz(platz_id)
{
    if(document.getElementById(platz_id).style.backgroundColor == "rgb(0, 168, 0)")
    {
        document.getElementById(platz_id).style.backgroundColor = "blue";
        return;
    }
    document.getElementById(platz_id).style.backgroundColor = "rgb(0, 168, 0)";
}
<div class='div_platz' onclick='selected_platz(this.id)' id='".$row['platz_id']."'>".$counter."</div>

React doesn’t update component on change Array – Leaflet

I have an Array that has a boolean variable that decides which data is shown and which is not, those values ​​are changed from a checkbox in another component, what happens to me is that when updating the array, the map is not updated to the new data. If the message is not understood it is because I am using a translator.

import './Leaflet.css'
import React from "react";
import { MapContainer, TileLayer,} from 'react-leaflet'
import { Data } from '../../components/data/SidebarData'
import SubMapa from './SubMapa';
function Mapa() {
    const referencia = useRef();
    const center = [8.890498870150504, -80.1123046875]
    console.log(`hola`)
    return (
        <>
            <MapContainer center={center} zoom={8}>
                <TileLayer
                    attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
                    url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
                />
                {Data.map((items, index) => {

                    return <SubMapa items={items} key={index} />
                })}
            </MapContainer>
            
        </>
    ) 
}
export default Mapa;

The script attribute used in html cannot run as expected [duplicate]

This is an example from w3school, I practice typing html, but I don’t know where is the problem
My intention is for the button to hide the city element, but somehow the button doesn’t work.

<!DOCTYPE html>
<html>
    <head>
        <meta charset = "utf-8">
    </head>
    <body>
        <button onclick = "myFunction()">Hide Elements</button>
        <h2 class = "London">London</h2>
        <p>london is beautiful.</p>

        <h2 class = "Tokyo">Tokyo</h2>
        <p>Tokyo is beautiful.</p>

        <h2 class = "Paris">Paris</h2>
        <p>Paris is beautiful.</p>

        <script>
            function myFunction(){
                var x = document.getElementsByClassName("city");
                for(var i= 0;i < x.length;i++){
                    x[i].style.display = "none";
                }
            }
        </script>
    </body>
</html>

How to implement sorting in mat-table using angular7

I am trying to implement sorting in using angular version 7.3.

Below is my source code:

<table
  mat-table
  [dataSource]='dataSource'>
  <ng-container matColumnDef="position">
    <th mat-header-cell *matHeaderCellDef> No. </th>
    <td mat-cell *matCellDef="let element"> {{element.position}} </td>
  </ng-container>
  <ng-container matColumnDef="name">
    <th mat-header-cell *matHeaderCellDef> Name </th>
    <td mat-cell *matCellDef="let element"> {{element.name}} </td>
  </ng-container>
  <ng-container matColumnDef="weight">
    <th mat-header-cell *matHeaderCellDef> Weight </th>
    <td mat-cell *matCellDef="let element"> {{element.weight}} </td>
  </ng-container>
</table>

Here is the javascript file source is:

const ELEMENT_DATA: PeriodicElement[] = [
  {position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H'},
  {position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'},
  {position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li'},
  {position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be'}
];

@Component({
  selector: 'table-basic-example',
  styleUrls: ['table-basic-example.css'],
  templateUrl: 'table-basic-example.html',
})
export class TableBasicExample {
  displayedColumns: string[] = ['position', 'name', 'weight', 'symbol'];
  dataSource = ELEMENT_DATA;
}

I am using angular version 7 and the sorting feature I am not able to write. Need help in that as I am new to angular

How to write a recursive function without setTimeout [closed]

Is there a way to make this function recursive without using setTimeout? Basically once all the work for the choicesObj[answer.choice]() is complete, I want to recall the prompt with the choices list. The problem right now is that it will call the prompt after 2 seconds even if the associated function with choicesObj[answer.choice]() is not done running.

const choicesObj = {
    'View all departments': viewDepartments, 
    'View all roles': viewRoles, 
    'View all employees': viewEmployees,
    'View employees by manager': viewByManager,
    'View employees by department': viewByDepartment, 
    'Add a department': addDepartment, 
    'Add a role': addRole,
    'Add an employee': addEmployee, 
    'Update an employee role': updateRole,
    'Update employee manager': updateManager,
    'Delete a department': deleteDepartment,
    'Delete a role': deleteRole,
    'Delete an employee': deleteEmployee,
    'EXIT': exitApp
}
const prompt = async () => {
    const answer = await inquirer.prompt({
        name: 'choice',
        type: 'list',
        message: 'What would you like to do?',
        choices: Object.keys(choicesObj)
    })
    if (answer) {
        choicesObj[answer.choice](); 
        setTimeout(function(){
            prompt(); // recursion after 2s
        }, 2000);
    }
};

Testing a react component using custom hooks with crud operations functions

I am trying to test a functional component (AddTodo). AddTodo is using a custom hooks which is returning todoList, addItemInTodoList and other functions. I’m mocking the custom hook and using mockResolvedValueOnce to set the todoList and other functions. Is this the right approach to test react component using custom hook.

Here is my AddTodo component

import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import useTodoList from '../hooks/useTodoList';
import Button from '../Components/button';
import Input from '../Components/input';

function AddTodo() {
  const navigate = useNavigate();
  
  const { todoList, addItemInTodoList } = useTodoList();
  const [todoText, setTodoText] = useState('');

  const handleTodoTextChange = (e) => {
    if(e.key === 'Enter') {
      handleAddItemClick();
      return;
    };
    setTodoText(e.target.value);
  };

  const handleAddItemClick = async () => {
    let data = {
      key: todoList.length + 1,
      text: todoText,
      date: new Date().toLocaleString()
    };
    const result = await addItemInTodoList(data);
    if (result) {
      navigate('/');
    }
  };

  return (
    <div className='flex flex-col w-25'>
      <h2>Add Todo Item</h2>
      <div className='flex'>
        <Input placeholder='Write something' value={todoText} onChange={handleTodoTextChange} onKeyPress={handleTodoTextChange} />
        <Button type='primary' value='Add' onClick={handleAddItemClick} />
      </div>
    </div>
  );
}

export default AddTodo;

Here is my useTodo custom Hook

import { useState, useEffect } from 'react';

export default function useTodoList(todoItemKey) {
  const CACHE_NAME = "todo-list";
  const ENDPOINT = "https://localhost:3000";

  const [todoList, setTodoList] = useState([]);

  const [selectedTodoItem, setSelectedTodoItem] = useState({});

  useEffect(() => {
    const todoItem = todoList.find(item => item.key === parseInt(todoItemKey));
    setSelectedTodoItem(todoItem);
  }, [todoList]);

  useEffect(() => {
    const getTodoList = async () => {
      try {
        const cache = await caches.open(CACHE_NAME);
        const response = await cache.match(ENDPOINT);

        if (!response) {
          return;
        }

        const responseBody = await response.json();
        setTodoList(responseBody);
      } catch (error) {
        console.log("getToken error:", { error });
      }
    };
    getTodoList();
  }, []);

  const addItemInTodoList = async (data) => {
    const updatedTodoList = [...todoList, data]
    try {
      const cache = await caches.open(CACHE_NAME);
      const responseBody = JSON.stringify(updatedTodoList);
      const response = new Response(responseBody);
      await cache.put(ENDPOINT, response);
      return true;
    } catch (error) {
      console.log("saveToken error:", { error });
      return false;
    }
  };

  const updateItemInTodoList = async (data) => {
    let updatedTodoList = todoList.filter(item => item.key !== data.key);
    updatedTodoList = [...updatedTodoList, data];
    updatedTodoList = updatedTodoList.sort((a, b) => new Date(a.date) - new Date(b.date));
    try {
      const cache = await caches.open(CACHE_NAME);
      const responseBody = JSON.stringify(updatedTodoList);
      const response = new Response(responseBody);
      await cache.put(ENDPOINT, response);
      return true;
    } catch (error) {
      console.log("saveToken error:", { error });
    }
  };

  const deleteItemInTodoList = async (todoItemKey) => {
    const updatedTodoList = todoList.filter(item => item.key !== todoItemKey);
    try {
      const cache = await caches.open(CACHE_NAME);
      const responseBody = JSON.stringify(updatedTodoList);
      const response = new Response(responseBody);
      await cache.put(ENDPOINT, response);
      setTodoList(updatedTodoList);
    } catch (error) {
      console.log("saveToken error:", { error });
    }
  };

  return { todoList, addItemInTodoList, updateItemInTodoList, deleteItemInTodoList, selectedTodoItem, setSelectedTodoItem };
}

Here is my AddTodo test

import { fireEvent, getByText, render } from '@testing-library/react';
import '@testing-library/jest-dom';
import { MemoryRouter } from 'react-router-dom';
import useTodoList from '../hooks/useTodoList';
import AddTodo from '../Pages/AddTodo';

jest.mock('../hooks/useTodoList');

afterEach(() => {
  jest.clearAllMocks()
})

test('should render add todo page', () => {
  useTodoList.mockResolvedValueOnce({ todoList: [], addItemInTodoList: () => { }, updateItemInTodoList: () => { }, deleteItemInTodoList: () => { }, selectedTodoItem: {}, setSelectedTodoItem: () => { } });
  const { getByPlaceholderText } = render(
    <MemoryRouter>
      <AddTodo />
    </MemoryRouter>
  );

  const input = getByPlaceholderText(/write something/i);
  expect(input).toBeInTheDocument();

  fireEvent.change(input, { target: { value: 'Todo Item 1'} });

  const btn = getByText(/add/i);
  fireEvent.click(btn);

  expect(addItemInTodoList).toBeCalledWith(/todo item 1/i);
});

Interpreting Uniswap V3 prices

I am quite new to Javascript and Uniswap. I am using Uniswap V3 to fetch the price from the DAI/USDC pool. My “main” funciton looks as follows:

async function main() {

  const [immutables, state] = await Promise.all([
    getPoolImmutables(),
    getPoolState(),
  ]);

  const DAI = new Token(1, immutables.token0, 18, "DAI", "Stablecoin");
  const USDC = new Token(1, immutables.token1, 6, "USDC", "USD Coin");

  const DAI_USDC_POOL = new Pool(
    DAI,
    USDC,
    immutables.fee,
    state.sqrtPriceX96.toString(),
    state.liquidity.toString(),
    state.tick
  );
  
  const token0Price = DAI_USDC_POOL.token0Price;

  console.log("The price is: ", token0Price);
}

And I am getting the following output:

The price is:  Price {
  numerator: JSBI(6) [
    435696740,
    805184612,
    508287463,
    671994784,
    427409972,
    4,
    sign: false
  ],
  denominator: JSBI(7) [ 0, 0, 0, 0, 0, 0, 4096, sign: false ],
  baseCurrency: Token {
    chainId: 1,
    decimals: 18,
    symbol: 'DAI',
    name: 'Stablecoin',
    isNative: false,
    isToken: true,
    address: '0x6B175474E89094C44Da98b954EedeAC495271d0F'
  },
  quoteCurrency: Token {
    chainId: 1,
    decimals: 6,
    symbol: 'USDC',
    name: 'USD Coin',
    isNative: false,
    isToken: true,
    address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'
  },
  scalar: Fraction {
    numerator: JSBI(2) [ 660865024, 931322574, sign: false ],
    denominator: JSBI(1) [ 1000000, sign: false ]
  }
}

The USDC price seems to make some sense (denominator, 1000000), however I am not sure how to interpret the DAI price from the output. If anyone can provide any hints or point me to a resource that explains the output, I would highly appreciate it. Thanks!