Can't redirect after action taken
Im losing my marbles on this one.
I'm using from react-router-dom to try to redirect to 1 of 2 pages.
But i can't get the redirect to work for the LIFE of me.
My log response payload is:
Which is great that shows redirectUrl is being chosen correctly and gpt4o is giving me the ideal response.
So why no redirect :sadboi: , i would use but thats in new router-dom.
useHistory
useHistory
[ Server ] Response payload: {
[ Server ] message: 'Webhook received and processed',
[ Server ] gptResponse: '2',
[ Server ] redirectUrl: '/not-a-good-fit'
[ Server ] }
[ Server ] Response payload: {
[ Server ] message: 'Webhook received and processed',
[ Server ] gptResponse: '2',
[ Server ] redirectUrl: '/not-a-good-fit'
[ Server ] }
useNavigate
useNavigate
import React, { useEffect, useRef, useState } from 'react';
import { useHistory } from 'react-router-dom';
declare global {
interface Window {
Tally: any;
}
}
const ApplicationForm: React.FC = () => {
const iframeRef = useRef<HTMLIFrameElement>(null);
const [isLoading, setIsLoading] = useState(false);
const history = useHistory();
useEffect(() => {
const script = document.createElement('script');
script.src = 'https://tally.so/widgets/embed.js';
script.async = true;
script.onload = () => {
if (window.Tally) {
window.Tally.loadEmbeds();
} else {
document.querySelectorAll("iframe[data-tally-src]:not([src])").forEach((iframe) => {
iframe.setAttribute('src', iframe.getAttribute('data-tally-src')!);
});
}
};
script.onerror = () => {
document.querySelectorAll("iframe[data-tally-src]:not([src])").forEach((iframe) => {
iframe.setAttribute('src', iframe.getAttribute('data-tally-src')!);
});
};
document.body.appendChild(script);
window.addEventListener('message', handleFormSubmit);
return () => {
document.body.removeChild(script);
window.removeEventListener('message', handleFormSubmit);
};
}, []);
const handleFormSubmit = async (event: MessageEvent) => {
console.log('Received message event:', event);
console.log('Event data:', event.data);
console.log('Event origin:', event.origin);
console.log('Event type:', event.type);
if (event.origin === 'https://tally.so' && event.data?.event === 'Tally.FormSubmitted') {
const formData = event.data.payload;
console.log('Form data received:', formData);
setIsLoading(true);
try {
const response = await fetch('https://b168-99-250-72-13.ngrok-free.app/webhook/callback', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(formData),
});
console.log('Response received:', response);
if (!response.ok) {
throw new Error('Error calling webhook');
}
const data = await response.json();
console.log('Response data:', data);
const gptResponse = data.gptResponse;
console.log('GPT-4 Response:', gptResponse);
const redirectUrl = data.redirectUrl;
console.log('Redirect URL:', redirectUrl);
if (redirectUrl) {
console.log('Redirecting to', redirectUrl);
history.push(redirectUrl);
} else {
console.error('Unexpected GPT-4 response or missing redirect URL:', gptResponse);
}
} catch (error) {
console.error('Error calling webhook:', error);
} finally {
setIsLoading(false);
}
}
};
return (
<div className="container mx-auto px-6 py-12">
{isLoading ? (
<div>Loading...</div>
) : (
<iframe
ref={iframeRef}
data-tally-src="https://tally.so/embed/3E118B?alignLeft=1&hideTitle=1&transparentBackground=1&dynamicHeight=1"
loading="lazy"
width="100%"
height="1239"
frameBorder="0"
marginHeight={0}
marginWidth={0}
title="AI Engineer Application"
></iframe>
)}
</div>
);
};
export default ApplicationForm;
import React, { useEffect, useRef, useState } from 'react';
import { useHistory } from 'react-router-dom';
declare global {
interface Window {
Tally: any;
}
}
const ApplicationForm: React.FC = () => {
const iframeRef = useRef<HTMLIFrameElement>(null);
const [isLoading, setIsLoading] = useState(false);
const history = useHistory();
useEffect(() => {
const script = document.createElement('script');
script.src = 'https://tally.so/widgets/embed.js';
script.async = true;
script.onload = () => {
if (window.Tally) {
window.Tally.loadEmbeds();
} else {
document.querySelectorAll("iframe[data-tally-src]:not([src])").forEach((iframe) => {
iframe.setAttribute('src', iframe.getAttribute('data-tally-src')!);
});
}
};
script.onerror = () => {
document.querySelectorAll("iframe[data-tally-src]:not([src])").forEach((iframe) => {
iframe.setAttribute('src', iframe.getAttribute('data-tally-src')!);
});
};
document.body.appendChild(script);
window.addEventListener('message', handleFormSubmit);
return () => {
document.body.removeChild(script);
window.removeEventListener('message', handleFormSubmit);
};
}, []);
const handleFormSubmit = async (event: MessageEvent) => {
console.log('Received message event:', event);
console.log('Event data:', event.data);
console.log('Event origin:', event.origin);
console.log('Event type:', event.type);
if (event.origin === 'https://tally.so' && event.data?.event === 'Tally.FormSubmitted') {
const formData = event.data.payload;
console.log('Form data received:', formData);
setIsLoading(true);
try {
const response = await fetch('https://b168-99-250-72-13.ngrok-free.app/webhook/callback', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(formData),
});
console.log('Response received:', response);
if (!response.ok) {
throw new Error('Error calling webhook');
}
const data = await response.json();
console.log('Response data:', data);
const gptResponse = data.gptResponse;
console.log('GPT-4 Response:', gptResponse);
const redirectUrl = data.redirectUrl;
console.log('Redirect URL:', redirectUrl);
if (redirectUrl) {
console.log('Redirecting to', redirectUrl);
history.push(redirectUrl);
} else {
console.error('Unexpected GPT-4 response or missing redirect URL:', gptResponse);
}
} catch (error) {
console.error('Error calling webhook:', error);
} finally {
setIsLoading(false);
}
}
};
return (
<div className="container mx-auto px-6 py-12">
{isLoading ? (
<div>Loading...</div>
) : (
<iframe
ref={iframeRef}
data-tally-src="https://tally.so/embed/3E118B?alignLeft=1&hideTitle=1&transparentBackground=1&dynamicHeight=1"
loading="lazy"
width="100%"
height="1239"
frameBorder="0"
marginHeight={0}
marginWidth={0}
title="AI Engineer Application"
></iframe>
)}
</div>
);
};
export default ApplicationForm;
10 Replies
Hi @Jacob Ferrari. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
Sorry @Jacob Ferrari, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist:
Perhaps try again in 15mins?
@kapa.ai
Let me check the knowledge base for you. One moment! :books:
Sorry @Jacob Ferrari, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist:
Perhaps try again in 15mins?
Ok let me take a look!
I will repost your code but with
js
afte the three backticks to get it to color it nicely so we can look at it more easily:
import React, { useEffect, useRef, useState } from 'react';
import { useHistory } from 'react-router-dom';
declare global {
interface Window {
Tally: any;
}
}
const ApplicationForm: React.FC = () => {
const iframeRef = useRef<HTMLIFrameElement>(null);
const [isLoading, setIsLoading] = useState(false);
const history = useHistory();
useEffect(() => {
const script = document.createElement('script');
script.src = 'https://tally.so/widgets/embed.js';
script.async = true;
script.onload = () => {
if (window.Tally) {
window.Tally.loadEmbeds();
} else {
document.querySelectorAll("iframe[data-tally-src]:not([src])").forEach((iframe) => {
iframe.setAttribute('src', iframe.getAttribute('data-tally-src')!);
});
}
};
script.onerror = () => {
document.querySelectorAll("iframe[data-tally-src]:not([src])").forEach((iframe) => {
iframe.setAttribute('src', iframe.getAttribute('data-tally-src')!);
});
};
document.body.appendChild(script);
window.addEventListener('message', handleFormSubmit);
return () => {
document.body.removeChild(script);
window.removeEventListener('message', handleFormSubmit);
};
}, []);
const handleFormSubmit = async (event: MessageEvent) => {
console.log('Received message event:', event);
console.log('Event data:', event.data);
console.log('Event origin:', event.origin);
console.log('Event type:', event.type);
if (event.origin === 'https://tally.so' && event.data?.event === 'Tally.FormSubmitted') {
const formData = event.data.payload;
console.log('Form data received:', formData);
setIsLoading(true);
try {
const response = await fetch('https://b168-99-250-72-13.ngrok-free.app/webhook/callback', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(formData),
});
console.log('Response received:', response);
if (!response.ok) {
throw new Error('Error calling webhook');
}
const data = await response.json();
console.log('Response data:', data);
const gptResponse = data.gptResponse;
console.log('GPT-4 Response:', gptResponse);
const redirectUrl = data.redirectUrl;
console.log('Redirect URL:', redirectUrl);
if (redirectUrl) {
console.log('Redirecting to', redirectUrl);
history.push(redirectUrl);
} else {
console.error('Unexpected GPT-4 response or missing redirect URL:', gptResponse);
}
} catch (error) {
console.error('Error calling webhook:', error);
} finally {
setIsLoading(false);
}
}
};
return (
<div className="container mx-auto px-6 py-12">
{isLoading ? (
<div>Loading...</div>
) : (
<iframe
ref={iframeRef}
data-tally-src="https://tally.so/embed/3E118B?alignLeft=1&hideTitle=1&transparentBackground=1&dynamicHeight=1"
loading="lazy"
width="100%"
height="1239"
frameBorder="0"
marginHeight={0}
marginWidth={0}
title="AI Engineer Application"
></iframe>
)}
</div>
);
};
export default ApplicationForm;
import React, { useEffect, useRef, useState } from 'react';
import { useHistory } from 'react-router-dom';
declare global {
interface Window {
Tally: any;
}
}
const ApplicationForm: React.FC = () => {
const iframeRef = useRef<HTMLIFrameElement>(null);
const [isLoading, setIsLoading] = useState(false);
const history = useHistory();
useEffect(() => {
const script = document.createElement('script');
script.src = 'https://tally.so/widgets/embed.js';
script.async = true;
script.onload = () => {
if (window.Tally) {
window.Tally.loadEmbeds();
} else {
document.querySelectorAll("iframe[data-tally-src]:not([src])").forEach((iframe) => {
iframe.setAttribute('src', iframe.getAttribute('data-tally-src')!);
});
}
};
script.onerror = () => {
document.querySelectorAll("iframe[data-tally-src]:not([src])").forEach((iframe) => {
iframe.setAttribute('src', iframe.getAttribute('data-tally-src')!);
});
};
document.body.appendChild(script);
window.addEventListener('message', handleFormSubmit);
return () => {
document.body.removeChild(script);
window.removeEventListener('message', handleFormSubmit);
};
}, []);
const handleFormSubmit = async (event: MessageEvent) => {
console.log('Received message event:', event);
console.log('Event data:', event.data);
console.log('Event origin:', event.origin);
console.log('Event type:', event.type);
if (event.origin === 'https://tally.so' && event.data?.event === 'Tally.FormSubmitted') {
const formData = event.data.payload;
console.log('Form data received:', formData);
setIsLoading(true);
try {
const response = await fetch('https://b168-99-250-72-13.ngrok-free.app/webhook/callback', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(formData),
});
console.log('Response received:', response);
if (!response.ok) {
throw new Error('Error calling webhook');
}
const data = await response.json();
console.log('Response data:', data);
const gptResponse = data.gptResponse;
console.log('GPT-4 Response:', gptResponse);
const redirectUrl = data.redirectUrl;
console.log('Redirect URL:', redirectUrl);
if (redirectUrl) {
console.log('Redirecting to', redirectUrl);
history.push(redirectUrl);
} else {
console.error('Unexpected GPT-4 response or missing redirect URL:', gptResponse);
}
} catch (error) {
console.error('Error calling webhook:', error);
} finally {
setIsLoading(false);
}
}
};
return (
<div className="container mx-auto px-6 py-12">
{isLoading ? (
<div>Loading...</div>
) : (
<iframe
ref={iframeRef}
data-tally-src="https://tally.so/embed/3E118B?alignLeft=1&hideTitle=1&transparentBackground=1&dynamicHeight=1"
loading="lazy"
width="100%"
height="1239"
frameBorder="0"
marginHeight={0}
marginWidth={0}
title="AI Engineer Application"
></iframe>
)}
</div>
);
};
export default ApplicationForm;
Here is the webhook part.
js
import express from 'express';
import { type WebhookCallback } from 'wasp/server/api';
import { type MiddlewareConfigFn } from 'wasp/server';
import { processWithGPT4 } from 'wasp/server/operations';
export const webhookCallback: WebhookCallback = async (req, res, context) => {
try {
const formDataBuffer = req.body;
console.log('Received webhook data:', formDataBuffer);
// Convert Buffer to JSON
const formData = JSON.parse(formDataBuffer.toString());
console.log('Parsed webhook data:', formData);
// Create the prompt
const prompt = `Output "1" if the user has answered the questions decently and above, they just have to have minimum decent answers.
Output "2" if the user did not do well with the questions and really wouldn't be a good fit: ${JSON.stringify(formData)} ONLY output 1 or 2 NOTHING ELSE.`;
// Extract temperature from formData, if available
const temperature = formData.temperature !== undefined ? formData.temperature : 0.3;
// Call the processWithGPT4 action
const gptResponse = await processWithGPT4({ data: formData, prompt, temperature }, { ...context, isWebhook: true });
console.log('GPT-4 Response:', gptResponse);
// Determine the redirect URL based on the GPT-4 response
const redirectUrl = gptResponse.trim() === '1' ? '/interview' : '/not-a-good-fit';
const responsePayload = { message: 'Webhook received and processed', gptResponse, redirectUrl };
console.log('Response payload:', responsePayload);
res.status(200).json(responsePayload);
} catch (error) {
console.error('Error processing webhook:', error);
res.status(500).json({ error: 'Internal Server Error' });
}
};
export const webhookCallbackMiddlewareFn: MiddlewareConfigFn = (middlewareConfig) => {
console.log('webhookCallbackMiddlewareFn: Swap express.json for express.raw');
middlewareConfig.delete('express.json');
middlewareConfig.set('express.raw', express.raw({ type: '*/*' }));
return middlewareConfig;
};
js
import express from 'express';
import { type WebhookCallback } from 'wasp/server/api';
import { type MiddlewareConfigFn } from 'wasp/server';
import { processWithGPT4 } from 'wasp/server/operations';
export const webhookCallback: WebhookCallback = async (req, res, context) => {
try {
const formDataBuffer = req.body;
console.log('Received webhook data:', formDataBuffer);
// Convert Buffer to JSON
const formData = JSON.parse(formDataBuffer.toString());
console.log('Parsed webhook data:', formData);
// Create the prompt
const prompt = `Output "1" if the user has answered the questions decently and above, they just have to have minimum decent answers.
Output "2" if the user did not do well with the questions and really wouldn't be a good fit: ${JSON.stringify(formData)} ONLY output 1 or 2 NOTHING ELSE.`;
// Extract temperature from formData, if available
const temperature = formData.temperature !== undefined ? formData.temperature : 0.3;
// Call the processWithGPT4 action
const gptResponse = await processWithGPT4({ data: formData, prompt, temperature }, { ...context, isWebhook: true });
console.log('GPT-4 Response:', gptResponse);
// Determine the redirect URL based on the GPT-4 response
const redirectUrl = gptResponse.trim() === '1' ? '/interview' : '/not-a-good-fit';
const responsePayload = { message: 'Webhook received and processed', gptResponse, redirectUrl };
console.log('Response payload:', responsePayload);
res.status(200).json(responsePayload);
} catch (error) {
console.error('Error processing webhook:', error);
res.status(500).json({ error: 'Internal Server Error' });
}
};
export const webhookCallbackMiddlewareFn: MiddlewareConfigFn = (middlewareConfig) => {
console.log('webhookCallbackMiddlewareFn: Swap express.json for express.raw');
middlewareConfig.delete('express.json');
middlewareConfig.set('express.raw', express.raw({ type: '*/*' }));
return middlewareConfig;
};
Ok, so this line
console.log('Redirecting to', redirectUrl);
, just above history.push
, does that trigger? What does it print in your browser dev console?
Btw history
should be working in general, here is a link to discord convo where Wasp user used it successfully just recently: https://discord.com/channels/686873244791210014/1249056983802183740/1249743840500387931 .
So "js" -> put it as a very next character after the last of the three backticks. So you want to have:@Jacob Ferrari , hi, did you ever figure this out? I was going to suggest something along the lines of
I do something similar in my project. I think you just want to make sure the redirectUrl is ready, and THEN redirect. Just make sure you aren't redirecting prior to having the data.
Hope you firgure it out!
await response.json().then(res => {
try {
history.push(res.redirectUrl);
} catch (err) {
console.log(err)
}
})
}
await response.json().then(res => {
try {
history.push(res.redirectUrl);
} catch (err) {
console.log(err)
}
})
}
Hi @JLegendz Thanks for this!! That is probably the solution but putting it on the backburner for now while i tackle other projects!
No worries!