Trying to import Email.js CDN with Next.js - reactjs

Cant find a concrete answer on how to import this correctly.
Email js is installed via NPM
I try to import it with HEAD tag
<Head>
<script type="text/javascript"
src="https://cdn.jsdelivr.net/npm/emailjs-com#2/dist/email.min.js">
</script>
<script type="text/javascript">
(function(){
emailjs.init("YOUR_USER_ID");
})();
</script></Head>
And i keep getting emailjs is undefined. No worries i will not be using next js again this was a mistake.

Here is an example from their npm package documentation. When using NextJS, you should generally use import or require
import emailjs from 'emailjs-com';
const templateParams = {
name: 'James',
notes: 'Check this out!'
};
emailjs.send('<YOUR SERVICE ID>','<YOUR TEMPLATE ID>', templateParams, '<YOUR USER ID>')
.then((response) => {
console.log('SUCCESS!', response.status, response.text);
}, (err) => {
console.log('FAILED...', err);
});

Related

Typescript, React, Vite, Express: Cannot fetch data on the frontend

I am building an app with Express on the backend and React on the frontend with typescript, and I am using Vite to build the frontend (my first time using Vite). My APIs are working fine, yet I am unable to fetch the data on the frontend. The simplified code on the frontend:
React.useEffect(() => {
const fetchData = async () => {
const response = await fetch("/api/data");
const json = await response.json();
if (response.ok) {
setData(json);
}
};
fetchData();
}, []);
It keeps sending me this html in the response:
<!DOCTYPE html>
<html lang="en">
<head>
<script type="module">
import RefreshRuntime from "/#react-refresh"
RefreshRuntime.injectIntoGlobalHook(window)
window.$RefreshReg$ = () => {}
window.$RefreshSig$ = () => (type) => type
window.__vite_plugin_react_preamble_installed__ = true
</script>
<script type="module" src="/#vite/client"></script>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx?t=1675714554862"></script>
</body>
</html>
I have tried to add the mentioned scripts in my html file, but the error persits. I am not sure if it could be maybe in the vite.config.ts:
export default defineConfig({
build: {
outDir: "dist",
},
server: {
port: 3001,
},
plugins: [react()],
});
I have allowed proxy in the package.json file to handle CORS but that doesn't seem to be the problem. I think I am overlooking something important but I am not sure what...Can anybody help?
You'll want to setup a proxy inside your Vite config.
https://vitejs.dev/config/server-options.html#server-proxy
Assuming your API listens on port 3000, add this proxy property to your server object:
server: {
proxy: {
'/api': {
target: 'http://localhost:3000',
changeOrigin: true,
secure: false
}
}
}

Cannot get react components with Cypress + cypress-react-selector

I'm trying to setup React testing with Cypress + cypress-react-selector.
Cypress seems to be working fine, but cypress-react-selector not so much.
I can run normal cypress methods.
But when I run cy.react(), it throws: "Could not find instance of React in given element"
I've been googling a lot, but nothing helps.
MyComponent.js
`
import React from 'react';
export const MyComponent = () => {
return <div data-testid="myTestId">my text</div>;
};
`
MyComponent.cy.js
`
import React from 'react';
import { MyComponent } from './MyComponent';
describe('<MyComponent />', () => {
beforeEach(() => {
cy.mount(<MyComponent />);
});
it('renders', () => {
//this works
cy.get('[data-testid=myTestId]').should('have.text', 'my text');
//this seems to be working, but I don't know
cy.waitForReact(5000, '#__cy_root');
//This fails with: "Could not find instance of React in given element"
cy.react('MyComponent');
});
});
`
cypress/support/component.js
`
import 'cypress-react-selector';
import './commands';
import { mount } from 'cypress/react18';
Cypress.Commands.add('mount', mount);`
cypress/support/component-index.html
`
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title>Components App</title>
</head>
<body>
<div id="__cy_root" data-cy-root></div>
</body>
</html>
`
cypress.config.js
`
const { defineConfig } = require('cypress');
module.exports = defineConfig({
env: {
'cypress-react-selector': {
root: '#__cy_root',
},
},
component: {
devServer: {
framework: 'create-react-app',
bundler: 'webpack',
},
},
});
`
Ask for code, if I haven't provided something.
cypress-react-selector pre-dates cypress component testing, and I don't see any sign that it has been updated to handle component testing - all examples are e2e style testing.
Logically, Cypress built-in component testing and cypress-react-selector do the same thing, so maybe consider using one or the other.
IMO the cypress-react-selector has somewhat better API and more accessible examples, for instance I can't see how to do this in Cypress component testing
cypress-react-selector#sample-tests
Get current state
cy.getReact('MyTextInput', {
props: { field: { name: 'email' } },
}).getCurrentState(); // can return string | boolean | any[] | {}

Adding Truepush initalization code to Gatsby

I am using GatsbyJS. Recently I created a file in which I put this code.
import React from 'react'
import { Helmet } from 'react-helmet'
const CustomScript = () => {
return (
<Helmet>
<script type="application/javascript" src="https://sdki.truepush.com/sdk/v2.0.2/app.js" async></script>
<script>
var truepush = window.truepush || [];
truepush.push(function(){
truepush.Init({
id: "..."
},function(error){
if(error) console.error(error);
})
})
</script>
</Helmet>
)
}
export default CustomScript
But it gives me this error
ERROR #98123 WEBPACK
Generating development JavaScript bundle failed
/home/lilynicole/GitLab/portfolio/src/components/CustomScript.js
12:17 error 'truepush' is not defined no-undef
✖ 1 problem (1 error, 0 warnings)
File: src/components/CustomScript.js
failed Re-building development bundle - 5.401s
I have tried couple of things but nothing seems to work. Any help will be really appreciated.
If you want to insert inline JavaScript (the second <script> tag) with React Helmet, you'd need to quote the entire JavaScript as follows:
import React from 'react'
import { Helmet } from 'react-helmet'
const CustomScript = () => {
return (
<Helmet>
<script type="application/javascript" src="https://sdki.truepush.com/sdk/v2.0.2/app.js" async></script>
<script>{`
var truepush = window.truepush || [];
truepush.push(function(){
truepush.Init({
id: "..."
},function(error){
if(error) console.error(error);
})
})
`}
</script>
</Helmet>
)
}
export default CustomScript
The only change is that I wrapped the entire content of the <script> tag in {` ... `}.
In any case, I'd find it cleaner to write the following:
import React from 'react'
import { Helmet } from 'react-helmet'
import { useEffect } from 'react'
const CustomScript = () => {
useEffect(() => {
var truepush = window.truepush || []
truepush.push(function () {
truepush.Init(
{
id: '...',
},
function (error) {
if (error) console.error(error)
}
)
})
}, [])
return (
<Helmet>
<script
type="application/javascript"
src="https://sdki.truepush.com/sdk/v2.0.2/app.js"
async
></script>
</Helmet>
)
}
export default CustomScript
Here, instead of treating the JavaScript for the initialization as a string you're actually including it in your component code.
To make sure it runs only once you wrap it with useEffect(() => {...}, []).
(Note that I edited out your private Truepush ID and replaced it with ...; you'll need to put it back in)
I am David from Truepush Tech support. Can you please tell me if the project that you are doing is "a WebSite" or "a WebApp".
As if you are building a website then the code please try using the method that #ehrencrona has given out. That is Code by #ehrencrona
But if it is a webapp, we are not supporting them as of now and can't help you with setting it up for them.
We are working on a solution for this from our end as well. We will let you know when we have something that we can give out to help you.

React component rendered twice using server side rendering

I have an app where I configured server side rendering. Everything is working nice and my component is rendered on the server. The problem is that I get my component rendered twice on the screen. One comes from <div id="content"><%- content %></div>that I am using for server rendering and one comes from <script src="http://localhost:3001/bundle.js"></script>. I use webpack to make two bundles for my server and client. Why is this happening and how can I fix this?
views/index.ejs
<body>
<div id="app"></div>
<div id="content"><%- content %></div>
<script src="http://localhost:3001/bundle.js"></script>
</body>
index.js
app.use(Express.static(path.join(__dirname, '../', 'dist')))
app.use(serverRenderer)
app.get('*', (req: Object, res: Object) => {
res.render('index', {content: req.body})
})
serverRender
import React from 'react'
import ReactDOM from 'react-dom/server'
import { match, RouterContext } from 'react-router'
import routes from '../client/routes.js'
async function render (component) {
const content = ReactDOM.renderToString(component)
return content
}
async function getMatchParams (routes, currentUrl) {
return new Promise((resolve, reject) => {
match({routes: routes, location: currentUrl}, (err, redirect, props) => {
if (err) {
return reject(err)
}
return resolve(props)
})
})
}
export default async(req, res, next) => {
const renderProps = await getMatchParams(routes, req.url)
if (renderProps) {
const component = (
<RouterContext {...renderProps} />
)
req.body = await render(component)
next()
}
}
Ok. I have found a problem. I was referring to the bundle and server rendered string with two separate <div>. Inside my app.js I was doing this
render(
<Router history={browserHistory}>
{routes}
</Router>,
document.getElementById('app')
)
Thats why I should have been sending the string to the template like this.
app.use(Express.static(path.join(__dirname, '../', 'dist')))
app.use(serverRenderer)
app.get('*', (req: Object, res: Object) => {
res.render('index', {app: req.body})
})
And finally my views/index.js should look like this
<body>
<div id="app"><%- app %></div>
<script src="http://localhost:3001/bundle.js"></script>
</body>
I also faced that problem and found a solution.
On package.json,
"start": "npm-run-all --parallel dev:*",
It will run webpack and node build/bundle.js.
Then 2 things happened simultaneously, webpack build project, node build/bundle.js
After webpack built project, then node build/bundle.js runs again since bundle.js is changed.
So there was twice calls on both server and client side. I solved this problem very easily.
First run npm run build, then run node build/bunde.js . Then it will run everything once :)

how does webpack import from external url

I am using webpack to manage my react application. Now I want to import a dependency from this url:
<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=gNO2wKVBNupZfafi0bl0sW3dIKqAHn4l">
traditionally I just put above code on my index.html file. But now how can I let webpack to load this url? And how my react js use that dependency?
when I launch webpack-dev-server, I will get below error:
ERROR in Entry module not found: Error: Cannot resolve module 'http://api.map.baidu.com/api'
Then I use little loader to load the url. Below is the javascript code to use loader:
import $ from 'jquery'
import React from 'react';
import ReactDOM from 'react-dom';
import load from 'little-loader';
import './main.css';
import './component';
import Search from './search/search'
load('http://api.map.baidu.com/api?v=2.0&ak=gNO2wKVBNupZfafi0bl0sW3dIKqAHn4l', function(err){
console.log('err:', err);
});
// document.body.appendChild(component());
ReactDOM.render(<Search />, document.getElementById('search'));
but I still got below error when launch webpack:
ERROR in Entry module not found: Error: Cannot resolve module 'http://api.map.baidu.com/api' in /Users/yzzhao/dev/react-demo/webpack_demo
In the future you should be able to use dynamic requires via System.import.
Webpack 2 will support them natively.
System.import('<url>')
.then(function() {
console.log('Loaded!');
});
If you don't want to wait for it, you could use a script loading library.
Example:
Install:
npm install little-loader --save
Use:
import load from 'little-loader';
load('<url>', (err) => {
})
Or do it manually
function load(url) {
return new Promise((resolve, reject) => {
var script = document.createElement('script')
script.type = 'text/javascript';
script.async = true;
script.src = url;
script.onload = resolve;
script.onerror = reject;
document.head.appendChild(script);
})
}
load('<url>')
.then(() => {
console.log('Loaded!');
})
.catch((err) => {
console.error('Something went wrong!', err);
})

Resources