How can I fix these console.log errors after using iframe embed google map in reactjs component? - node.js

iframe used in react component:
import React from 'react';
const StoreMapLocation = () => {
return (
<div>
<iframe
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d14387.771831185173!2d102.77328521573708!3d25.640018633937373!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x36da58403c9938ef%3A0x2ad1b6679ae45280!2sJijiexiang%2C%20Xundian%20Hui%20and%20Yi%20Autonomous%20County%2C%20Kunming%2C%20Yunnan%2C%20%E0%A6%9A%E0%A7%80%E0%A6%A8%2C%20655213!5e0!3m2!1sbn!2sbd!4v1651750063366!5m2!1sbn!2sbd"
className="h-96 w-full border-2 rounded-lg shadow-lg" allowFullScreen="" loading="lazy"></iframe>
</div>
);
};
export default StoreMapLocation;
console log error:
google.maps.event.addDomListener() is deprecated, use the standard addEventListener() method instead: https://developer.mozilla.org/docs/Web/API/EventTarget/addEventListener
The feature will continue to work and there is no plan to decommission it.

Related

Load specific DIV with a react component without reloading the whole page

I have a menu where every menu item is a button and I want to load a specific reactjs component into a specific div without reloading the whole page.
This is the current code, clearly is bad but I don't know where to start fixing it...
...
<Button onClick={this.loadTarget}>
{menuItem.name}
</Button>
...
loadTarget(event) {
document.getElementById("datapanel").innerHTML="abc<TranslationsList />";
}
When I click a menu Item I want to load my div with the value "abc<TranslationsList />". "abc" is displayed but the custom component "TranslationsList" is not and I guess this is normal as the TranslationsList tag is not a HTML tag. But how could I load my component?
I could use links instead of buttons but in this case the question is how could I update the div content with a specific link?
It's hard if you've programmed plain JS before, but you have to forget the "good old JS pattern" in React. I also had a hard time getting used to not using standard JS elements (target, innerHTML, etc.) to solve such a problem.
So the solution in React is to use the framework and your page reload problem will be solved immediately. useState for the state of the component and handlers for the click. My main code looks like this. You can find a working application at Codesandbox.
export default function App() {
const [showComponent, setShowComponent] = useState(false);
const handleButtonClick = (e) => {
setShowComponent(!showComponent);
};
return (
<div className="App">
<h1>
Load specific DIV with a react component without reloading the whole
page
</h1>
<a href="https://stackoverflow.com/questions/74654088/load-specific-div-with-a-react-component-without-reloading-the-whole-page">
Link to Stackoverflow
</a>
<div style={{ marginTop: "20px" }}>
<button onClick={handleButtonClick}>Magic</button>
</div>
{showComponent ? (
<div style={{ marginTop: "20px" }}>
This is the place of your component!
</div>
) : (
""
)}
</div>
);
}
In the first place I wpuld not use vanilla JS syntax on a react app if it is not necessary. i.e: document.getElementById("datapanel").innerHTML="abc<TranslationsList />".
If you are using React you should be managing the State in the component of the DIV, giving the order to make an element appear once the button is clicked.
A simple example can be this:
CodeSandbox
import { useState } from "react";
export default function App() {
const [divState, setDivState] = useState(null);
const divElement = () => <div>I am the element that should appear</div>;
const handleDiv = () => {
setDivState(divElement);
};
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<button onClick={handleDiv}>Show DIV</button>
<div>{divState}</div>
</div>
);
}
I agree with the answers given above. Since you are already using React, you should take advantage of its features/functionalities. No need to reinvent the wheel.
However, if you are still interested in how to make your current implementation work. You may use renderToString(), which can be imported from ReactDOMServer. Please refer to the following code snippet as an example.
import { renderToString } from 'react-dom/server'
const TranslationsList = () => {
return <div>TranslationsList Content</div>
}
export default function App() {
const loadTarget = () => {
document.getElementById("datapanel").innerHTML=`abc${renderToString(<TranslationsList />)}`;
}
return (
<div>
<button onClick={loadTarget}>Insert Component</button>
<div id="datapanel">Data Panel Holder</div>
</div>
);
}

Why can React display an object but not its members?

I'm trying to wrap my head around the MERN stack. So far I've managed to query my database and get the data on an API endopoint, but I'm having some trouble getting it to show up on my front-end.
Here's my fronted code :
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class App extends Component<{}, {res:any}> {
constructor(props:any) {
super(props);
this.state = {res: Array};
}
callAPI() {
fetch("http://localhost:5000")
.then(res => res.json())
.then(json => this.setState({res: json}));
}
componentWillMount() {
this.callAPI();
}
render() {
// WORKS
console.log(this.state.res[0]);
// DOESN'T WORK
console.log(this.state.res[0].name);
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.tsx</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
)};
}
export default App;
As you can see it's just a modified version of the default React homepage. I just added a state and fetching data from my backend.
The problem comes when I try to console.log my data.
If I console.log(this.state.res[0]), everything is fine, and I get { "_id": "62207b47d40bca8ea8b60560", "name": "Patère", "checked": false, "links": [ "" ] } in my console. But if I try to only log the name, I get Uncaught TypeError: this.state.res[0] is undefined, which is weird, since it managed to display this.state.res[0] just fine before ?
What's causing this and how can I fix it ?
Thank you in advance.

How do I create show page based on id of item clicked

I am creating list of items looped through .map function. I want each of these items be rendered in a single page with some other details.
import React from 'react'
import {faArrowRight, faMusic, faPlay, faPlayCircle, faTachometerAlt} from "#fortawesome/free-solid-svg-icons";
import {FontAwesomeIcon} from "#fortawesome/react-fontawesome";
import music from '../mocks/music.json'
import { Link } from 'gatsby'
import Music from '../pages/music'
const newData = music.map( (data) => {
return (
<div className="row no-gutters justify-content-between align-items-center">
<div className="col-auto">
<button className="btn-gradient btn-circle">
<FontAwesomeIcon icon={faPlayCircle} />
</button>
</div>
<div className="col">
<div className="music-list-content">
<span className="artist">{data.author}</span>
<Link to={`/music/${data.id}`}>{data.title}</Link>
<span className="play">
<FontAwesomeIcon icon={faPlay} /> {data.duration}
</span>
</div>
</div>
<div className="col-auto">
<span className="badge-dark badge">{data.genre}</span>
</div>
</div>
)
})
const membersToRender = music.filter(member => member.id)
const numRows = membersToRender.length
const Musics = () => {
return (
<div>
<div className="title">
<h5>New Music</h5>
<span>{numRows} new songs</span>
</div>
<div>
<div className="music-list card-wrapper">
{newData}
</div>
</div>
<div className="footer-wrapper">
<div>
<FontAwesomeIcon icon={faMusic} />
<span>Song Library</span>
</div>
<FontAwesomeIcon icon={faArrowRight} />
</div>
</div>
)
}
export default Musics
I created a link which whenever I click, it takes me to another page (page not found) with id appended and .js extension.
Please, how do go about it? I want a click on the title and have it displayed on a full page.
Your logic seems good, however, you are missing the most important part, the page creation, since you are not creating the pages, all of your links are broken.
In Gatsby, you have two different ways of creating pages:
Using gatsby-node.js to create pages dynamically: when dealing with a huge amount of data, like your JSON, it's easier to let Gatsby deal with this responsibility of creating pages for Gatsby. Since you are sourcing from a JSON, you need everything set to create dynamic pages.
const path = require("path")
// Implement the Gatsby API “createPages”. This is called once the
// data layer is bootstrapped to let plugins create pages from data.
exports.createPages = async ({ graphql, actions, reporter }) => {
const { createPage } = actions
const musics= require("./data/mocks/musics.json")
const musicTemplate = path.resolve(`src/templates/music-template.js`)
musics.forEach(music) => {
createPage({
path: `/music/${music.slug}`
component: musicTemplate,
context: {
title: music.title,
description: music.description,
// and so on for the rest of the fields
},
})
})
}
Note: I'm assuming that your JSON is properly defined and formatted, having all the fields I queried.
Your musicTemplate must be a template (inside /templates folder).
Notice that you are passing some fields through Gatsby's context, this means that those fields will be available through props.pageContext in your template. So, there, create a template like:
import React from "react"
import Layout from "../components/layout"
export default function MusicTemplate({pageContext}) {
return (
<Layout>
<div>Hello musician {pageContext.title}</div>
</Layout>
)
}
So, as I said, with this approach you are creating dynamic pages based on your JSON file, and they will be available inside localhost:8000/music/{music.slug}, and all your reference and links that point there, will be valid.
I would also recommend using static query/useStaticQuery to retrieve data from your JSON in that loop. If you create a static query from that data (in a separate component) you will be able to fetch it on-demand across your project, so you will be reusing an interesting part of logic. It's better to use it rather than requesting a JSON directly.
You can follow this guide from the great Jason Lengstorf which is mostly what you need.
Adding .js files in your /pages folder: Gatsby infers the internal structure of your /pages folder and will create pages accordingly to that structure. For instance, if you have a structure like: /pages/musicians/name1.js Gatsby will create a page like localhost:8000/musicians/name1.
As it has been said, the first approach fits your requirements and it's preferred for this use-cases, since the second one will be less scalable and maintainable.
You should do some routing with React-Router (https://reactrouter.com/web/example/basic).
So the link have to point to a Route in a Switch, as is in the example of the link.

Monitoring multiple server stats in React JS

I have multiple pods running on my Kubernetes cluster and I have a "core app" built with react from which I want to get CPU & Memory usage stats.
Right now I am testing using a very simple setup where I have a local node app using socket.io to stream the time (based on this tutorial)
However, with one component which looks like the following, I am able to get real time updates from the server.
import React, { useState, useEffect } from "react";
import socketIOClient from "socket.io-client";
import {StatsCPUWrapper} from './statsCPU.style'
const ENDPOINT = process.env.STATS_ENDPOINT || "http://127.0.0.1:4001";
function StatsCPUComp() {
const [cpustats, setCPUstats] = useState("");
useEffect(() => {
const socket = socketIOClient(ENDPOINT);
socket.on("FromAPI", data => {
setCPUstats(data);
});
// Clean up the effect
return () => socket.disconnect();
}, []);
return (
<StatsCPUWrapper>
<p>
It's <time dateTime={cpustats}>{cpustats}</time>
</p>
</StatsCPUWrapper>
);
}
export default StatsCPUComp;
What I am now trying to do is have 3 or more of those components (depends on the list I get from my backend) to "subscribe" to multiple servers at the same time.
Here's my "projects list" component which gets the stats from the initial state and renders all the details:
import React from 'react'
import {useSelector, useDispatch} from 'react-redux'
import {Link} from 'react-router-dom'
import PropTypes from 'prop-types'
import {create, remove} from '../../features/projects/projectSlice'
import {ProjectWrapper} from './project.style'
import StatsCPUComp from './stats/statsCPU'
export function ProjectComp() {
const dispatch = useDispatch()
const projects = useSelector((state) => state.projects)
const handleSubmit = (e) => {
e.preventDefault()
}
const handleAction = (e) => {
e.preventDefault()
}
return (
<ProjectWrapper>
<div className="projects">
<div className="row">
{projects.map((projects) => (
<div className="col-12">
<div class="card project-card">
<div className="card-body">
<div className="row">
<div className="col-4 project-text">
<h5 class="card-title">
{' '}
<Link to={`/projects/` + projects.id}>{projects.name}</Link>
</h5>
<p class="card-text">Owner: {projects.owner}</p>
<p class="card-text">{projects.email}</p>
</div>
<div className="col-4 projects-stats">
<StatsCPUComp />
</div>
<div className="col-4 projects-stats"></div>
<div className="col-4 projects-stats"></div>
</div>
</div>
</div>
<br></br>
</div>
))}
</div>
</div>
</ProjectWrapper>
)
}
Right now the "time" from the stats component is being added on my last project component (makes sense since I did not implement any approach yet to map that too).
Any ideas on how I can have a different stats component for each of my "projects" where each one connects to a provided endpoint ? (I can pass all of the endpoints as env variables)
Any help would be highly appreciated.
So here's the implementation I did to make it work. (Not sure if it's ideal so please feel free to make any suggestions)
I added "endpoint" to state.projects which holds the data I get from my backend.
Then in my "projects list" component mentioned shown in the question, I pass projects (from state.projects) as props
<StatsCPUComp props={projects}/>
I then destructure it and pass it to my useEffect() in the stats component as follows:
import React, {useState, useEffect} from 'react'
import socketIOClient from 'socket.io-client'
import {StatsCPUWrapper} from './statsCPU.style'
import {useSelector, useDispatch} from 'react-redux'
let ENDPOINTS = []
let PROJECTS = []
function StatsCPUComp(...props) {
const [cpustats, setCPUstats] = useState('')
let endpoints = {...props}
let endpoints_2 = {...endpoints[0]}
useEffect(() => {
let socketlist = []
console.log(endpoints[0].props.endpoint)
const socket = socketIOClient(endpoints[0].props.endpoint);
socket.on("FromAPI", data => {
setCPUstats(data);
});
return () => socket.disconnect();
}, [cpustats])
return (
<>
<StatsCPUWrapper>
<p>
It's <time dateTime={cpustats}>{cpustats}</time>
</p>
</StatsCPUWrapper>
</>
)
}
export default StatsCPUComp
It seems to be working fine, however please do provide any suggestions since I might not be following an optimal approach (Performance and scalability wise)

Typescript Property '' does not exist on type 'never'. in React NodeJs stack

I am slowly teaching myself NodeJs, Express, React, monogoDB and Typescript.. (coming from a MVC C# SQL DB Background)
My very simple Hello world program just needs to communicate with the Express server to display a list of Users. My Express server is on Port 3001 and my Create-React-App Front end is on Port 3000.
my App Component is as follows:
import * as React from 'react';
import './App.css';
const logo = require('./logo.svg');
class App extends React.Component {
state = {users: []}
componentDidMount(){
console.log("Fetching Users");
fetch('/users')
.then(res=> res.json())
.then(users=> this.setState({users}));
}
render() {
return (
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h2>Welcome to React test</h2>
{this.state.users.map(user =>
<div key={user.id}>{user.username}</div>
)}
</div>
<p className="App-intro">
To get started, edit <code>src/App.tsx</code> and save to reload.
</p>
</div>
);
}
}
export default App;
The error:
(21,28): error TS2339: Property 'id' does not exist on type 'never'.
I can see the problem is that I havent defined users to include properties users.id and users.username.. But I am unsure how to do this?
I may have posted this question a bit to quickly.
but I solved my answer
import * as React from 'react';
import './App.css';
const logo = require('./logo.svg');
interface Iuser {
id: number,
username: string
}
class App extends React.Component {
state = {users: Array<Iuser>()}
componentDidMount(){
console.log("Fetching Users");
fetch('/users')
.then(res=> res.json())
.then(users=> this.setState({users}));
}
render() {
return (
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h2>Welcome to React test</h2>
{this.state.users.map(user =>
<div key={user.id}>{user.username}</div>
)}
</div>
<p className="App-intro">
To get started, edit <code>src/App.tsx</code> and save to reload.
</p>
</div>
);
}
}
export default App;
(Creating an interface for the array object)
I did try this previously but had the syntax wrong.

Resources