I get this error message in console while switiching from one page to another.
I dont think I am using the same component in both pages
I think it is a new error which might come with react19 but I am not sure
Any suggestion?
Blancer.com Tutorials and projects
Freelance Projects, Design and Programming Tutorials
Category Added in a WPeMatico Campaign
I get this error message in console while switiching from one page to another.
I dont think I am using the same component in both pages
I think it is a new error which might come with react19 but I am not sure
Any suggestion?
After creating a dynamic route [id] it contains 2 pages, a server side component where the error is and a client side PolicyVerificationClient.tsx which takes the params Certificatenumber and id.
import {
doc,
getDoc
} from 'firebase/firestore';
import {
db
} from '@/lib/firebase';
import PolicyVerificationClient from './PolicyVerificationClient';
type Props = {
params: Promise < {
id: string
} > ;
searchParams: {
[key: string]: string
};
}
export default async function PolicyVerificationPage({
params
}: Props) {
const resolvedParams = await params;
// Fetch initial data on the server
let certificateNumber = '';
try {
const docRef = doc(db, 'records', resolvedParams.id);
const docSnap = await getDoc(docRef);
if (docSnap.exists()) {
const data = docSnap.data();
certificateNumber = data.certificateNumber || '';
}
} catch (error) {
console.error('Error fetching record:', error);
}
return <PolicyVerificationClient id={resolvedParams.id} initialCertificateNumber={certificateNumber} />;
}
I keep getting a type error: Type ‘Props’ does not satisfy the constraint ‘PageProps’.
Types of property ‘searchParams’ are incompatible.
Type ‘{ [key: string]: string | string[] | undefined; }’ is missing the following properties from type ‘Promise’: then, catch, finally, [Symbol.toStringTag]
I tried this but it did not fix the problem searchParams: Promise<{ [key: string]: string | string[] | undefined }>; // Updated to be a Promise
I attempting to have a button (linked image or text) users can use to insert a templated paragraph of text into a specific section of a google doc. The templated text is a Header which has a checklist checkbox (when used, strikes out line), and includes an expandable bulleted list.
Example of the text script should input
I’ve mostly been able to build out how I want the template text to look, but haven’t found a solution online for placing it after specific text while remaining formatted, and also making the header a checklist.
I’ve found ways to place unformatted text, and ways to create checkbox lists, but nothing that includes the combinations I’m looking for.
I’ve found ways to place the cursor in a specific location and ways to “findtext”, but none that I was able to make work along with the specific formatted text I’m using.
Here’s an example google doc that includes the script I have so far.
Here’s the script so far:
function insertText() {
var headerFormatOn = {"BOLD": true, "BACKGROUND_COLOR": "#000000", "FOREGROUND_COLOR": "#FFFFFF"};
var formatOn = {"BOLD": true, "BACKGROUND_COLOR": "#000000", "FOREGROUND_COLOR": "#FFFFFF"};
var formatOff = {"BOLD": false, "BACKGROUND_COLOR": "#000000", "FOREGROUND_COLOR": "#FFFFFF"};
var header = "Enter_Item_Title_Here"
var bulletBody = ": ___________"
var bulletOneHeader = "Agenda Item Owner(s): ___________"
var bulletTwoHeader = "Discussant: ___________"
var bulletThreeHeader = "Discussion Date: ___________"
var bulletFourHeader = "External follow up: ___________"
var bulletFiveHeader = "Notes: ___________"
var bulletSixHeader = "Action Items: ___________"
var attributes1 = Object.entries(headerFormatOn).reduce((o, [k, v]) => Object.assign(o, {[k]: v}), {});
///var attributes2 = Object.entries(formatOn).reduce((o, [k, v]) => Object.assign(o, {[k]: v}), {});
///var attributes3 = Object.entries(formatOff).reduce((o, [k, v]) => Object.assign(o, {[k]: v}), {});
var cursor = DocumentApp.getActiveDocument().getActiveTab().asDocumentTab().getBody();
var text1 = cursor.appendParagraph(header);
text1.setHeading(DocumentApp.ParagraphHeading.HEADING3);
///var text2 = cursor.insertText(bulletBody);
///text2.setAttributes(attributes3);
var text3 = cursor.appendListItem(bulletOneHeader);
//text3.setAttributes(attributes2);
text3.setGlyphType(DocumentApp.GlyphType.BULLET).setGlyphType(DocumentApp.GlyphType.BULLET);
var text4 = cursor.appendListItem(bulletTwoHeader);
//text4.setAttributes(attributes2);
text4.setGlyphType(DocumentApp.GlyphType.BULLET);
var text5 = cursor.appendListItem(bulletThreeHeader);
text5.setGlyphType(DocumentApp.GlyphType.BULLET);
var text6 = cursor.appendListItem(bulletFourHeader);
text6.setGlyphType(DocumentApp.GlyphType.BULLET);
var text7 = cursor.appendListItem(bulletFiveHeader);
text7.setGlyphType(DocumentApp.GlyphType.BULLET);
var text8 = cursor.appendListItem(bulletSixHeader);
text8.setGlyphType(DocumentApp.GlyphType.BULLET);
var text9 = cursor.appendListItem(bulletSixHeader);
text9.setGlyphType(DocumentApp.GlyphType.BULLET);
}
I have a feeling some of it might have to do with “append” vs “insert”, or some of the variations I’ve read about in my searching, but I haven’t been able to figure out which pieces need to change in order for it to work.
I’m currently developing an Angular app which displays customizable real-time charts. Basically we’re fetching data from a database that get its data from a MQTT server.
To customize the chart, I added a little button which opens a PrimeNG modal, where you can change trace color (handled with a HTML color input) and the time range over which data is displayed.
The issue is that, since it’s real time data, it get updated every seconds or so (this will be configurable as well), which has for now two disadvantages :
This is the update function, which is called everytime the component receive a new data from the parent component :
private _dataGraph!: GraphLastDataTopicsDetailsModel[] | null;
@Input()
get iDataGraph(): GraphLastDataTopicsDetailsModel[] | null {
return this._dataGraph;
}
set iDataGraph(data: GraphLastDataTopicsDetailsModel[] | null) {
if (data) {
this._dataGraph = data;
this.fillData(data);
}
}
fillData(dataGraphReceived: GraphLastDataTopicsDetailsModel[]) {
// Get data with correct title
let dataReceived = dataGraphReceived.find(el => el.name === this._layout.title.text);
if (dataReceived) {
let newTraces: PlotlyDataModel[] = [];
let oldData: PlotlyDataModel[] = this._data;
for (let currentTopic of dataReceived.dataTopics) {
const dataTopicGraph = oldData.find(el => el.name === currentTopic.topic);
if (dataTopicGraph) {
let newX = [...dataTopicGraph.x, currentTopic.date];
let newY = [...dataTopicGraph.y, currentTopic.dataDouble];
// To do : create a different way of cleaning the array after x seconds
if (newX.length > this._maxValues) {
newX.shift();
}
if (newY.length > this._maxValues) {
newY.shift();
}
// Push the current values in the trace array
newTraces.push(
{
...dataTopicGraph,
x: newX,
y: newY,
}
);
}
else {
// On init (no data yet), we push the values as well as the trace's options
this.rgbStringToHex(this.colors[newTraces.length])
newTraces.push(
{
x: [currentTopic.date],
y: [currentTopic.dataDouble],
type: 'scatter',
name: currentTopic.topic,
marker: { color: this.colors[newTraces.length] },
line: { shape: 'spline' },
mode: 'lines+markers',
connectgaps: true,
showlegend: true,
}
);
}
}
This is the HTML part :
<plotly-plot class="w-full" [data]="_data" [layout]="_layout" [config]="{ scrollZoom: true, displaylogo: false }" />
This is how the data is updated :
serviceSubscribe(): void {
// Get all words for screen
this._subscription.add(
this._getLastDataTopic$.pipe(
concatMap(variables => {
return this.getLastDataTopicService.getLastDataTopic(variables);
}),
tap(data => {
if (data) {
this._data = data;
// this._intervalTest = this._intervalTest + 1000;
this.realTimeService.setIntervalDuration(this._intervalTest);
} else {
console.warn('No data received');
// TODO: Ajouter un message toast ici pour notifier l'utilisateur
}
})
).subscribe()
);
this._subscription.add(
this.realTimeService.getRealTimeData().subscribe((data) => {
this.realTimeData = data;
this._getLastDataTopic$.next([
{ name: "Chart n°1", topicsName: ['adress/equipment1/Process1/temp'] },
{ name: "Chart n°2", topicsName: ['adress/equipment1/Process1/pressure1', 'adress/equipment1/Process1/pressure2'] }
]);
}));
}
We had to fetch data this way because we’ve had some issues with components completely refreshing each time otherwise. I’d like to know if there’s any solution to prevent this behavior (even if it only fixes the issue with the color picker it’d be amazing).
I’m building a React application where I want to map over an array of items and render them as a list. The issue I’m facing is when the state is initially undefined, the map() function throws the following error:
Uncaught TypeError: Cannot read property 'map' of undefined
Here is the simplified version of my code:
import React, { useState, useEffect } from 'react';
function ItemList() {
const [items, setItems] = useState(); // State initially undefined
useEffect(() => {
// Simulating an API call
setTimeout(() => {
setItems(['Item 1', 'Item 2', 'Item 3']);
}, 2000);
}, []);
return (
<div>
<h1>Item List</h1>
<ul>
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
</div>
);
}
export default ItemList;
What is the best way to avoid this error while ensuring that the component works smoothly even when the data is being fetched asynchronously? Should I use a default value for the state or apply another method to handle this case efficiently?
I have the following array example
userShifts = [
{ userId: 1, startTime: "05:00", endTime: "13:00" },
{ userId: 2, startTime: "05:00", endTime: "13:00" },
{ userId: 3, startTime: "05:00", endTime: "13:00" },
{ userId: 4, startTime: "13:00", endTime: "21:00" },
{ userId: 5, startTime: "13:00", endTime: "21:00" },
{ userId: 6, startTime: "13:00", endTime: "21:00" },
{ userId: 7, startTime: "21:00", endTime: "00:00" },
{ userId: 8, startTime: "21:00", endTime: "00:00" },
{ userId: 9, startTime: "21:00", endTime: "00:00" },
{ userId: 10, startTime: "07:00", endTime: "15:00" },
{ userId: 11, startTime: "07:00", endTime: "15:00" },
{ userId: 12, startTime: "03:00", endTime: "11:00" },
];
I need a function that will create a shift blokcs of 24 hours so from 00:to
00:00 and the next user start time cannot be before the end time fo the previous one so the output of the above array would be
userShiftBlocks = [
[
{ userId: 1, startTime: "05:00", endTime: "13:00" },
{ userId: 4, startTime: "13:00", endTime: "21:00" },
{ userId: 7, startTime: "21:00", endTime: "00:00" }
],
[
{ userId: 2, startTime: "05:00", endTime: "13:00" },
{ userId: 5, startTime: "13:00", endTime: "21:00" },
{ userId: 8, startTime: "21:00", endTime: "00:00" }
],
[
{ userId: 3, startTime: "05:00", endTime: "13:00" },
{ userId: 6, startTime: "13:00", endTime: "21:00" },
{ userId: 9, startTime: "21:00", endTime: "00:00" }
],
[
{ userId: 10, startTime: "07:00", endTime: "15:00" }
],
[
{ userId: 11, startTime: "07:00", endTime: "15:00" }
],
[
{ userId: 12, startTime: "03:00", endTime: "11:00" }
]
];
So for each block a 24 hour shift period , the start time of the next user is after or the same as the previous user end time. So an array like below where not everythign matched start end exactly should also work
userShifts = [
{ userId: 1, startTime: "05:00", endTime: "13:00" },
{ userId: 2, startTime: "05:00", endTime: "13:30" },
{ userId: 3, startTime: "05:00", endTime: "13:00" },
{ userId: 4, startTime: "13:00", endTime: "21:00" },
{ userId: 5, startTime: "14:30", endTime: "21:00" },
{ userId: 6, startTime: "13:00", endTime: "21:00" },
{ userId: 7, startTime: "21:30", endTime: "00:00" },
{ userId: 8, startTime: "21:00", endTime: "00:00" },
{ userId: 9, startTime: "21:00", endTime: "00:00" },
{ userId: 10, startTime: "07:00", endTime: "15:00" },
{ userId: 11, startTime: "07:00", endTime: "15:00" },
{ userId: 12, startTime: "03:00", endTime: "11:00" },
];
I am not gettig the results I want yet and chatgpt completely looses the plotso help is appreciated
I can’t understand why my return doesn’t return a dot from cases with the letters ‘b’ ‘y’ and a comma’,’ I put console.log, looked, shows a dot but at some level it’s still a comma and my functions don’t work with it. I need these symbols to turn into a dot both on the program code and visually. If anyone can solve the problem, please write why this is happening, I want to figure it out. Thanks!
const displayEl = document.querySelector('.display');
const buttonEls = [...document.querySelectorAll('.button')];
const cleanBtnEl = document.querySelector('.clean-btn');
const operators = ['+', '-', '*', '/'];
const focusInput = () => displayEl.focus();
focusInput();
window.addEventListener('click', () => focusInput());
displayEl.addEventListener('keydown', (e) => {
if (e.key === ' ') e.preventDefault();
if (displayEl.value.includes('e') || displayEl.value === 'Error') displayEl.value = '';
const key = e.key.toLowerCase();
const valueStr = handlerKey(key);
console.log(valueStr);
// if (valueStr === '.') {
// displayEl.value += valueStr;
// }
if (!displayEl.value) {
if (!blockFirstPoint(valueStr)) e.preventDefault();
}
if (!checkPointBeforeAndAfterOperator(valueStr)) e.preventDefault();
if (valueStr === '.') {
if (!limitPoints(valueStr)) e.preventDefault();
}
if (!displayEl.value) {
if (!blockFirstOperator(valueStr)) e.preventDefault();
}
if (operators.includes(valueStr)) {
if (!blockSpamOperators(valueStr)) e.preventDefault();
}
if (!replaceAndLimitZero(valueStr)) e.preventDefault();
if (valueStr === 'delete') clear();
if (valueStr === 'enter' || valueStr === '=') calc();
});
const handlerKey = (key) => {
switch (key) {
case 'f5':
case 'f12':
return key;
case 'enter':
return '=';
case ',':
case 'б':
case 'ю':
return '.';
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '+':
case '-':
case '*':
case '/':
case '.':
case 'backspace':
case 'delete':
case 'tab':
case 'arrowleft':
case 'arrowright':
case 'delete':
return key;
default:
return null;
}
};
buttonEls.forEach(button => {
button.addEventListener('click', () => {
if (displayEl.value.includes('e') || displayEl.value === 'Error') displayEl.value = '';
const valueStr = button.innerText;
if (!displayEl.value) {
if (!blockFirstPoint(valueStr)) return;
}
if (!displayEl.value) {
if (!blockFirstOperator(valueStr)) return;
}
if (!replaceAndLimitZero(valueStr)) return;
if (valueStr === '=') {
if (!calc()) return;
}
if (operators.includes(valueStr)) {
if (!blockSpamOperators(valueStr)) return;
}
if (!checkPointBeforeAndAfterOperator(valueStr)) return;
if (button.innerText === '.') {
if (!limitPoints(valueStr)) return;
}
displayEl.value += valueStr;
});
});
const blockFirstPoint = (valueStr) => {
if (valueStr === '.') return false;
return true;
};
const blockFirstOperator = (valueStr) => {
if (operators.includes(valueStr)) return false;
return true;
};
const replaceAndLimitZero = (valueStr) => {
const currentValue = displayEl.value;
const arrayNumbers = ['1', '2', '3', '4', '5', '6', '7', '8', '9'];
if (currentValue === '0' && valueStr === '0') {
return false;
} else if (currentValue === '0' && arrayNumbers.includes(valueStr)) {
displayEl.value = '';
return true;
}
const lastOperatorIndex = Math.max(...operators.map(op => currentValue.lastIndexOf(op)));
const afterLastOperator = currentValue.slice(lastOperatorIndex + 1);
if (lastOperatorIndex !== -1) {
if (afterLastOperator === '0' && valueStr === '0') {
return false;
} else if (afterLastOperator === '0' && arrayNumbers.includes(valueStr)) {
displayEl.value = currentValue.slice(0, -1);
}
}
return true;
};
const blockSpamOperators = (valueStr) => {
const currentValue = displayEl.value;
const lastChair = currentValue[currentValue.length - 1];
if (operators.includes(lastChair)) displayEl.value = currentValue.slice(0, -1) + valueStr;
if (operators.some(op => currentValue.includes(op))) return false;
return true;
};
const checkPointBeforeAndAfterOperator = (valueStr) => {
const currentValue = displayEl.value;
let lastChar = displayEl.value[currentValue.length - 1];
if (operators.includes(lastChar)) {
if (valueStr === '.') return false;
return true;
}
if (lastChar === '.' && operators.includes(valueStr)) return false;
return true;
};
const limitPoints = (point) => {
const lastOperator = operators.find(op => displayEl.value.includes(op));
const currentOperator = lastOperator ? displayEl.value.split(lastOperator).pop() : displayEl.value;
if (currentOperator.includes(point)) return false;
return true;
};
const calc = () => {
const currentValue = displayEl.value;
const lastChar = displayEl.value[currentValue.length - 1];
if (lastChar === '.') return false;
const operator = operators.find(op => currentValue.includes(op));
const [firstValueStr, secondValueStr] = currentValue.split(operator);
const firstNumber = parseFloat(firstValueStr);
const secondNumber = parseFloat(secondValueStr);
let result;
if (isNaN(secondNumber)) return;
switch (operator) {
case '+':
result = firstNumber + secondNumber;
break;
case '-':
result = firstNumber - secondNumber;
if (0 > result) {
displayEl.value = 'Error';
return;
}
break;
case '*':
result = firstNumber * secondNumber;
break;
case '/':
if (secondNumber === 0) {
displayEl.value = 'Error';
return;
}
result = firstNumber / secondNumber;
break;
default:
displayEl.value = 'Error';
}
const res = result.toString();
if (res.includes('e')) {
displayEl.value = result;
return;
}
displayEl.value = Math.round(result * 100_000_000) / 100_000_000;
};
cleanBtnEl.addEventListener('pointerdown', () => {
deleteLastCharacter();
let clearIntervalId;
const clearTimeoutId = setTimeout(() => {
clearIntervalId = setInterval(() => {
deleteLastCharacter();
}, 50);
}, 500);
const clearTime = () => {
clearTimeout(clearTimeoutId);
clearInterval(clearIntervalId);
};
cleanBtnEl.addEventListener('pointerup', clearTime);
window.addEventListener('pointerup', clearTime);
});
const deleteLastCharacter = () => {
const currentValue = displayEl.value;
const cursorPosition = displayEl.selectionStart;
if (cursorPosition === 0) {
return;
} else {
displayEl.value = currentValue.slice(0, cursorPosition - 1) + currentValue.slice(cursorPosition);
}
displayEl.setSelectionRange(cursorPosition - 1, cursorPosition - 1);
};
const clear = () => displayEl.value = '';
I have a problem with rendering a component after a performing a navigate with state to another page. Everything works as expected when I am already on the page that I am navigating to, but I would like for it to work when I navigate from another page as well.
I have a “globally” defined keyboard listener that should navigate me to the desired page upon a sequence of keys (I’m using a barcode scanner).
const barcodeString = useRef("")
const recordingBarcode = useRef(false)
const scannerCallback = useCallback(
(e) => {
if (e.key === "$") {
recordingBarcode.current = true;
} else if (e.key === "Enter" && recordingBarcode.current) {
recordingBarcode.current = false;
navigate("/box/build", {state:{barcode:barcodeString.current}});
barcodeString.current = ""
} else if (recordingBarcode.current) {
barcodeString.current = barcodeString.current + e.key;
}
},
[],
);
useEffect(() => {
document.addEventListener('keydown', scannerCallback);
return () => {
document.removeEventListener('keydown', scannerCallback);
};
}, [scannerCallback]);
If I press the sequence “$4Enter” it successfully navigates to the "/box/build" page
<Route path='/box/build'
element={<BuildBoxPage buildBoxRequest={buildBoxRequest}
getRecipesRequest={getRecipesRequest}
/>}/>
In the BuildBoxPage I do the following
const BuildBoxPage = ({buildBoxRequest, getRecipesRequest}) => {
const {state} = useLocation();
const [box, setBox] = useState();
const [boxes, setBoxes] = useState([]);
const [boxNumber, setBoxNumber] = useState();
const [recipes, setRecipes] = useState([]);
const [ingredients, setIngredients] = useState([]);
const [supplements, setSupplements] = useState([]);
useEffect(() => {
if (state != undefined) {
updateBox(state.barcode)
}
}, [state]);
const updateBox = (barcode) => {
setBoxNumber(barcode);
// == to compare a string value with an int on purpose
setBox(boxes.find(box => box.box_number == barcode));
}
...
}
This updates the select with the state value (boxNumber) that I am using for choosing a box, but doesn’t render the the BuildBoxForm component in response to choosing a select value.
return (<section className="bg-indigo-50 min-h-[calc(100vh-81px)]">
<div className="container m-auto max-w-2xl py-10">
<div
className="bg-white px-6 py-8 mb-4 shadow-md rounded-md border m-4 md:m-0"
>
<form autoComplete="off" onSubmit={submitForm}>
<h2 className="text-3xl text-center font-semibold mb-6">Build box</h2>
<div className="mb-4">
<label className="block text-gray-700 font-bold mb-2"
>Box Number</label
>
<select
id="boxNumber"
name="boxNumber"
className="border rounded w-full py-2 px-3 mb-2"
required
value={boxNumber}
defaultValue={"def"}
onChange={(e) => updateBox(e.target.value)}
>
<option hidden value={"def"}>Select a box to build</option>
{boxes.map((box) => (
<option key={box.box_number} value={box.box_number}>{box.box_number}</option>
))}
</select>
</div>
{
box !== undefined ?
<BuildBoxForm box={box} recipe={recipes[box.recipe_number - 1]} ingredients={ingredients}
setIngredients={setIngredients} supplements={supplements}
setSupplements={setSupplements}/> : <></>
}
</form>
</div>
</div>
</section>)
The result is the following if I am on the same page while navigating. This is the expected result and also the result I get if I manually select a box number in the select.
This is what I get if I am on another page while navigating, note that the number does update in the select but the BuildBoxForm is not rendered (because box is still undefined).
Any ideas of where I am going wrong here?
Please help me, how to use an Accelerometer to shake it
I want to achieve that when I shake my phone, the data increases and vibrates continuously. The data will continue to increase and vibrate continuously
Here is the code I am currently using. Although it responds when shaken, it is not smooth
if (window.Telegram?.WebApp?.Accelerometer) {
window.Telegram.WebApp.Accelerometer
.start({
frequency: 90
}, (started) => {
if (started) {
console.log('ok');
this.checkAccelerometer();
} else {
console.log('no');
}
});
}
checkAccelerometer() {
if (!window.Telegram?.WebApp?.Accelerometer?.isStarted) {
this.isShaking = false;
return;
}
const currentTime = new Date().getTime();
const x = window.Telegram.WebApp.Accelerometer.x;
const y = window.Telegram.WebApp.Accelerometer.y;
const z = window.Telegram.WebApp.Accelerometer.z;
if ((currentTime - this.lastUpdate) > this.timeThreshold) {
const diffTime = currentTime - this.lastUpdate;
const diffX = this.lastX - x;
const diffY = this.lastY - y;
const diffZ = this.lastZ - z;
const speed = Math.sqrt(diffX * diffX + diffY * diffY + diffZ * diffZ) / diffTime * 10000;
if (speed < this.minThreshold) {
if (this.isShaking) {
this.isShaking = false;
console.log('stop');
}
}
else if (speed > this.shakeThreshold &&
currentTime - this.lastShakeTime > this.shakeCooldown) {
this.onShake();
this.lastShakeTime = currentTime;
}
this.lastUpdate = currentTime;
this.lastX = x;
this.lastY = y;
this.lastZ = z;
}
requestAnimationFrame(this.checkAccelerometer);
},
I’m trying to understand how promises work under the hood in JS and faced with this example:
const promise = Promise.reject();
promise
.catch(() => console.log(1));
promise
.catch(() => console.log(2));
// Output:
// 1
// 2
const promise = Promise.reject();
promise
.catch(() => console.log(1))
.catch(() => console.log(2));
// Output:
// 1
Why do we have different outputs in similar examples?
Why catch is called second time in the first example?
Because promise is already rejected after the first catch, so it should be logical that the second catch should not be called in both cases…
I think the main reason here is how microtasks queue works but I’m not sure.
I do not seem to be able to use methods from the relativeTime Dayjs plugin in a large Vue 3 app. I have followed the instructions here: https://day.js.org/docs/en/plugin/relative-time
We have a vendors file which loads some external libs and adds them to Vue using the install method. In here I am loading the relativeTime and duration plugins and extending dayjs with them, like this:
import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';
import duration from 'dayjs/plugin/duration';
export default {
install: (app) => {
dayjs.extend(relativeTime);
dayjs.extend(duration);
app.config.globalProperties.$dayjs = dayjs;
}
}
Then, in a component elsewhere in the app, I am trying to use the from method like this:
const currentDate = this.$dayjs();
const prevDate = this.$dayjs(oldDate);
const datesDiff = this.$dayjs(prevDate).from(currentDate);
But the third line throws the error:
this.$dayjs(…).from is not a function.
I also tried to use it like this: prevDate.from(currentDate) but this gives the same error.
If I log out currentDate and prevDate, both are valid dayjs objects. I’m using TypeScript also, and if I hover the pointer on the from method, I can see the correct type for the method ((method) Dayjs.from(compared: ConfigType, withoutSuffix?: boolean): string), and I don’t get any TS intellisense errors in the editor or during compilation. It is only at runtime that I see the error.
On the other hand, I am able to use the duration plugin without any issues, so elsewhere in the app, I can call this.$dayjs.duration(date2 - date1) without any errors.
Am I doing something wrong, or is this a bug with the plugin?
Based on the comment from @estus, even if I import dayjs and the relativeTime plugin directly in my component, and use the exact example shown on the relativeTime plugin docs page like this:
import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';
export default {
name: 'my-component',
beforeMount() {
dayjs.extend(relativeTime);
},
mounted() {
console.log(dayjs().from(dayjs("1990-01-01"), true));
},
}
Then I still see the exact same error that from is not a function.
I am using Vue 3.5.6 and dayjs 1.11.13
I’m using Chart.js to display a line chart with custom tooltips. I have implemented the custom tooltip rendering logic using the external option in the tooltip plugin. However, when there are points with value: null, the external callback is not triggered, and no tooltip is shown for those points.
Here’s my current configuration:
plugins: {
tooltip: {
enabled: false,
// other options...
external: (context) => {
const { chart, tooltip } = context;
// my custom tooltip render logic...
}
}
}
I’ve tried various approaches but couldn’t find a way to make the external callback fire for null values. Is there any solution or workaround available?
Any help would be greatly appreciated!
I am working on a Web-GIS Project using three.js. I have a 3D Model in both .glb and .gltf formats that I have to display on a 3D OSM map. I have to add a functionality on the map where when I click on the model, it should open a popup displaying the information that will be input. All the other functionalities are working fine. But any functionality I give to the Model, it doesnt appear. I tried giving it a popup on mouseClick, hover, popup on keypress, color change on keypress, etc. I even tried making a Sidebar and having it open when I click on the Model. But none of it works, I am seeing no errors in the console either. Its my first time working with 3D Models so its really confusing for me.
Any guidance would be really helpful.
I have a hook to read OTP from sms in nextJS
import { useRouter } from 'next/router'
import { useEffect } from 'react'
const useAutoReadOtp = (handleSetOtp = (_: string) => {}, enabled = true) => {
const { isReady } = useRouter()
const ac = new AbortController()
useEffect(() => {
if (isReady && 'OTPCredential' in window && enabled) {
// Fetch OTP from SMS
navigator.credentials
.get({
otp: { transport: ['sms'] },
signal: ac.signal,
} as CredentialRequestOptions)
.then((otp: any) => {
if (otp && otp.code) {
handleSetOtp(otp.code)
}
})
.catch((err) => {
console.log('Error reading OTP:', err)
})
} else {
alert('Not supported Web OTP')
}
// Cleanup the AbortController on unmount or retry
return () => {
ac.abort()
}
}, [isReady, enabled, handleSetOtp])
}
export default useAutoReadOtp
If we allow the browser to read OTP from the popup then it works perfectly. But after denying on first try in next tries it opens the popup but does not work on clicking Allow.
I have tried to see if navigator.credentials.get is getting resolved or throwing error or anything by adding finally to the promise but it is not executed. Also nothing inside error, .catch or else is getting executed when I click on allow after clicking on Deny.
Can anyone give me an example for how to add Socks5/VLess connection in my react-native application?
I have an VPN application, with button “Connect” but can’t find any info about how to make connections in react-native.
My current const to make connections:
const connectVPN = async () => {
// If already connected, reset timer
if (isConnected) {
resetTimer();
return;
}
setConnecting(true);
// Retry logic up to maxAttempts
for (let i = 0; i < maxAttempts; i++) {
try {
const res = await fetch('http://localhost:8080/api/v1/credentials');
if (!res.ok) throw new Error("Failed to get credentials");
const data = await res.json();
const {username, password} = data;
const success = true;
if (success) {
setIsConnected(true);
setConnectionAttempts(0);
setConnecting(false);
resetTimer();
startTimer();
return;
} else {
throw new Error("VPN connect failed");
}
} catch (err) {
console.log(err);
setConnectionAttempts(i + 1);
}
}
setConnecting(false);
alert(t('error'));
};
After the credentials step I need to set connection to VPNServer using Socks5 or VLess protocols