A method of calling an api of node.js from react.js - node.js

After crawling a part of the university to node.js, we try to call an api of node.js to react.js.
In the node.js file, Title and url of the link were retrieved, and in the react.js file, List and ListItem were configured to receive api data.
The problem is that I don't know how to call tittle and url from react.js, which are data crawled in node.js.
Also, I ask because I don't know how to insert the called api into the list of react.js.
This is App.js :
import React from 'react';
import HeaderTemplate from './components/HeaderTemplate';
import MainTemplate from './components/MainTemplate';
import FooterTemplate from './components/FooterTemplate';
const App = () => {
return (
<div>
<HeaderTemplate/>
<MainTemplate/>
<FooterTemplate/>
</div>
);
};
export default App;
This is MainTemplate.js :
import React from 'react';
import styled from 'styled-components';
import NoticesList from './NoticesList';
const MainTemplate = () => {
const Main = {
display: 'flex',
flexDirection: 'row',
justifyContent: 'center',
padding: '60px',
};
const Section01 = {
margin: '25px',
width: '55%',
height: '80vh',
backgroundColor: '#eeeeee',
fontSize: '45px',
textAlign: 'center',
};
const Section02 = {
margin: '25px',
width: '45%',
height: '80vh',
backgroundColor: '#ff0000',
fontSize: '45px',
textAlign: 'center',
};
return (
<div className="Main" style={Main}>
<div className="Section01" style={Section01}>
비교과
<NoticesList />
</div>
<div className="Section02" style={Section02}>
튜터링 및 학공
</div>
</div>
);
};
export default MainTemplate;
This is NoticesItem.js :
import React from 'react';
import styled from 'styled-components';
const NoticesItemBlock = styled.div`
display: flex;
.contents {
h6 {
margin: 15px;
a {
color: black;
}
}
}
& + & {
margin-top: 1.5rem;
}
`;
const NoticesItem = ({ article }) => {
const { title, url } = article;
return (
<NoticesItemBlock>
<div className="contents">
<h6>
<a href={url} target="_blank" rel="noopener noreferrer">
{title}
</a>
</h6>
</div>
</NoticesItemBlock>
);
};
export default NoticesItem;
This is NoticesList.js :
import React from 'react';
import styled from 'styled-components';
import NoticesItem from './NoticesItem';
const NoticesListBlock = styled.div`
box-sizing: border-box;
padding-bottom: 3rem;
width: 768px;
margin: 0 auto;
margin-top: 2rem;
`;
const sampleArticle = {
title: 'title',
url: 'https://google.com',
};
const NoticesList = () => {
return (
<NoticesListBlock>
<NoticesItem article={sampleArticle} />
<NoticesItem article={sampleArticle} />
<NoticesItem article={sampleArticle} />
<NoticesItem article={sampleArticle} />
</NoticesListBlock>
);
};
export default NoticesList;

Related

Data only shows up when I click twice on submit on ReactJs

I'm trying to create a link shortener using Reactjs, after I set up the post request for the long URL, I need to display the resulting short URL. The problem is I can't seem to be able to do that. The resulting link only shows up when I click twice on the submit button, but if I refresh the page and click submit, the shortened link does not show up.
I'm hoping you can help me with that, here's my code:
import './App.css';
import Button from '#mui/material/Button';
import TextField from '#mui/material/TextField';
import React, {Component} from 'react';
import axios from 'axios'
class App extends Component {
constructor(){
super()
this.changelongUrl=this.changelongUrl.bind(this)
this.onSubmit=this.onSubmit.bind(this)
this.state={
longUrl:'',
shortenedUrl :[],
urls:[]
}
}
changelongUrl(event){
this.setState({
longUrl : event.target.value
})
}
onSubmit(event){
event.preventDefault()
const registered={
longUrl: this.state.longUrl
}
axios.post('http://localhost:5000/api/url/shorten',registered)
axios.get('http://localhost:5000/')
.then(response => {
this.setState({ urls: response.data });
console.log(this.state.urls)
})
this.setState({
shortenedUrl: this.state.urls.filter(url => url.longUrl === this.state.longUrl).map(filteredUrl => (
filteredUrl.shortUrl
))
})
console.log(this.state.shortenedUrl)
this.setState({
longUrl:''
})
}
render(){
return(
<div className="App">
<header className="App-header">
<form onSubmit={this.onSubmit} style={{
display: 'flex',
flexDirection: 'column'}}>
<TextField value={this.state.longUrl} onChange={this.changelongUrl}
style={{ marginBottom: 22 }} className="textfield" id="outlined-basic"
label="Please Input Your Link" variant="outlined" />
<Button style={{
marginBottom: 22,
backgroundColor: "#47597E",
padding: "10px 20px",
fontSize: "18px"}}
variant="contained" type= 'Submit'>Shorten</Button>
</form>
<a href={this.state.shortenedUrl}>{this.state.shortenedUrl}</a>
</header>
</div>)
}
}
export default App;

React navigation throwing error when moving between screens

I have defined two screens in my App.js.
import 'react-native-gesture-handler';
import * as React from 'react';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import HomeScreen from './HomeScreen';
import FAQScreen from './FAQScreen';
const Stack = createStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="HomeScreen">
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="FAQ" component={FAQScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
In my HomeScreen.js I want to simply press a button and navigate to FAQScreen.
However, I keep getting an error:
The action 'NAVIGATE' with payload {"name":FAQScreen}" was not handled by any navigator.
Do you have a screen named 'FAQScreen'?
I tried to do multiple Google search and found no solution to solve this.
Here is my HomeScreen.js for completeness.
mport 'react-native-gesture-handler';
import React, { Component } from 'react';
import { StyleSheet, Text, SafeAreaView, View, Button} from 'react-native';
class MyButtonText extends Component {
render() {
var phoneHeight = 500;
const myFontSize = phoneHeight/25;
return (
<Text style={{ fontFamily: "Courier New", fontSize: myFontSize }} onPress = {() => console.log("text clicked")}>
{this.props.children}
</Text>
);
}
}
class MyInfoText extends Component {
render() {
var phoneHeight = 500;
const myFontSize = phoneHeight/30;
return (
<Text numberOfLines = {2} style={{ fontFamily: "Courier New", fontSize: myFontSize, alignItems: "center", textAlign: "center"}}>
{this.props.children}
</Text>
);
}
}
function HomeScreen({ navigation }) {
const toolKaiserID = "alkjakljf";
navigateToScreen=()=>{
console.log('Going to FAQ screen now...');
navigation.navigate('FAQScreen')
}
return (
// this is a comment
<SafeAreaView style={styles.container}>
{/* top bar */}
<View style = {topBarStyle.container}>
<Button onPress={this.navigateToScreen} title="Information" />
<MyButtonText>ID: {toolKaiserID}</MyButtonText>
<Button title="Feedback"/>
</View>
{/* info bar */}
<View style = {infoBarStyle.container}>
<MyInfoText>paper on floor -- tool(s) on top; take photos from at least 3ft/1m away</MyInfoText>
</View>
{/* camera view */}
<View style = {cameraStyle.container}></View>
{/* bottom bar */}
<View style = {bottomBarStyle.container}>
<Button title="1 Photos"/>
<Button title="2 Check"/>
<Button title="3 Editor"/>
<Button title="4 Paper"/>
</View>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#434343',
},
});
const viewStyle = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'blue',
},
});
const topBarStyle = StyleSheet.create({
container: {
flex: 1,
flexDirection: "row",
justifyContent: 'space-around',
backgroundColor: 'blue',
},
});
const infoBarStyle = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'white',
},
});
const cameraStyle = StyleSheet.create({
container: {
flex: 5,
backgroundColor: 'red',
},
});
const bottomBarStyle = StyleSheet.create({
container: {
flex: 1,
flexDirection: "row",
justifyContent: 'space-around',
backgroundColor: 'yellow',
},
});
export default HomeScreen;
There is no FAQScreen name in your stack navigator
<Stack.Screen name="FAQ" component={FAQScreen} />
When you use navigate, it's need the name, that is "FAQ"
If you want to navigate using name "FAQScreen", you can set like this:
<Stack.Screen name="FAQScreen" component={FAQScreen} />

How to make GridList face vertically in One Row with React and materialUI on Mobile

How do I make Materia-UI GridList Face vertically in One Row on Mobile?
My GridList is two in a row which is what I wanted but when I inspect it on mobile it still shows two in a row instead of One. that means it's not responsive, How do I make it responsive?
this is my Events Component.
import React from "react";
import { Link } from "react-router-dom";
import axios from "axios";
import GridList from "#material-ui/core/GridList";
import GridListTile from "#material-ui/core/GridListTile";
import GridListTileBar from "#material-ui/core/GridListTileBar";
import ListSubheader from "#material-ui/core/ListSubheader";
mport IconButton from "#material-ui/core/IconButton";
import Button from "#material-ui/core/Button";
import { withStyles } from "#material-ui/core/styles";
import Typography from "#material-ui/core/Typography";
const useStyles = (theme) => ({
root: {
display: "flex",
flexWrap: "wrap",
justifyContent: "space-around",
overflow: "hidden",
backgroundColor: theme.palette.background.paper,
},
gridList: {
width: 1000,
height: 950,
},
icon: {
color: "rgba(255, 255, 255, 0.54)",
},
});
class EventsList extends React.Component {
constructor(props) {
super(props);
this.state = { events: [] };
}
componentDidMount() {
axios
.get("http://localhost:9000/events/")
.then((response) => {
this.setState({ events: response.data });
})
.catch(function (error) {
console.log(error);
});
}
render() {
const { classes } = this.props;
return (
<div className={classes.root}>
<GridList cellHeight={330} className={classes.gridList} spacing={8}>
<GridListTile key="Subheader" cols={2} style={{ height: "auto" }}>
<ListSubheader component="div">December</ListSubheader>
</GridListTile>
{this.state.events.map((tile) => (
<GridListTile key={tile.eventImage}>
<img src={tile.eventImage} alt={tile.title} />
<GridListTileBar title={tile.title} titlePosition="top" />
<GridListTileBar
paragraph={tile.description}
actionIcon={
<IconButton
aria-label={`info about ${tile.title}`}
className={classes.icon}
></IconButton>
}
/>
</GridListTile>
))}
</GridList>
</div>
);
}
}
export default withStyles(useStyles)(EventsList);
this is the List of my events displayed by GridList on Mobile
but something like this is what I want to see when I am on Mobile.
Since you are using class based component, you can use withWidth to conditionally set cols value to GridList.
See working example here in codesandbox
Example code snippet
class TitlebarGridList extends Component {
render() {
const { classes, width } = this.props; // <---- see here
let columns = width === "xs" || width === "sm" ? 1 : 2;
console.log("=========>", width);
return (
<div className={classes.root}>
<GridList cellHeight={200} className={classes.gridList} cols={columns}> {/* //<---- see here */}
<GridListTile key="Subheader" cols={3} style={{ height: "auto" }}>
<ListSubheader component="div">December</ListSubheader>
</GridListTile>
{tileData.map(tile => (
<GridListTile key={tile.title}>
<img className={classes.image} src={tile.img} alt={tile.title} />
</GridListTile>
))}
</GridList>
</div>
);
}
}
TitlebarGridList.propTypes = {
classes: PropTypes.object.isRequired
};
export default compose(
withStyles(styles, {
name: "TitlebarGridList"
}),
withWidth() //<---- see here
)(TitlebarGridList);
Note: withWidth will be deprecated sometime in the future, so consider to use useMediaQuery hook (in that case you have to switch to functional component).

How to use Material Ui on React. getting error Invalid Hook call

`×
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app`
I am new to React, my code was working fine but I decided to use MaterialUi today, now it's giving me errors, I have tried googling but I didn't succeed. Another thing is that my this.state.events is returning an Empty array, instead of a list of events. How do I fix this?
My React-dom version is ─ react-dom#16.13.1 and React version is ─ react#16.13.1
import React, { Component } from "react";
import { Link } from "react-router-dom";
import axios from "axios";
import { makeStyles } from "#material-ui/core/styles";
import GridList from "#material-ui/core/GridList";
import GridListTile from "#material-ui/core/GridListTile";
import GridListTileBar from "#material-ui/core/GridListTileBar";
import ListSubheader from "#material-ui/core/ListSubheader";
import IconButton from "#material-ui/core/IconButton";
export default class EventsList extends Component {
constructor(props) {
super(props);
this.state = { events: [] };
}
componentDidMount() {
axios
.get("http://localhost:9000/events/")
.then((response) => {
this.setState({ events: response.data });
})
.catch(function (error) {
console.log(error);
});
}
render() {
const useStyles = makeStyles((theme) => ({
root: {
display: "flex",
flexWrap: "wrap",
justifyContent: "space-around",
overflow: "hidden",
backgroundColor: theme.palette.background.paper,
},
gridList: {
width: 500,
height: 450,
},
icon: {
color: "rgba(255, 255, 255, 0.54)",
},
}));
const classes = useStyles();
return (
<div className={classes.root}>
<GridList cellHeight={180} className={classes.gridList}>
<GridListTile key="Subheader" cols={2} style={{ height: "auto" }}>
<ListSubheader component="div">December</ListSubheader>
</GridListTile>
{this.state.events.map((tile) => (
<GridListTile key={tile.img}>
<img src={tile.img} alt={tile.title} />
<GridListTileBar
title={tile.title}
subtitle={<span>by: {tile.author}</span>}
actionIcon={
<IconButton
aria-label={`info about ${tile.title}`}
className={classes.icon}
></IconButton>
}
/>
</GridListTile>
))}
</GridList>
</div>
);
}
}
makeStyles returns a hook i.e. useStyles. You can only use hooks in functional components.
One option is to convert your class component to functional. Also make sure to put makeStyles code outside of component(you don't want to execute it on every re-render)
import React, { useEffect, useState } from "react";
// other imports
const useStyles = makeStyles((theme) => ({
root: {
display: "flex",
flexWrap: "wrap",
justifyContent: "space-around",
overflow: "hidden",
backgroundColor: theme.palette.background.paper,
},
gridList: {
width: 500,
height: 450,
},
icon: {
color: "rgba(255, 255, 255, 0.54)",
},
}));
const EventsList = () => {
const [events, setEvents] = useState([]);
const classes = useStyles();
useEffect(() => {
axios
.get("http://localhost:9000/events/")
.then((response) => {
this.setState({ events: response.data });
})
.catch(function (error) {
console.log(error);
});
}, []);
return (
<div className={classes.root}>
// rest of code...
</div>
);
};
Another option is to keep class based component intact and use withStyles.
See withStyles API doc:
Use the function signature if you need to have access to the theme. It's provided as the first argument.
import { withStyles } from "#material-ui/core";
const styles = (theme) => ({
root: {
display: "flex",
flexWrap: "wrap",
justifyContent: "space-around",
overflow: "hidden",
backgroundColor: theme.palette.background.paper,
},
gridList: {
width: 500,
height: 450,
},
icon: {
color: "rgba(255, 255, 255, 0.54)",
},
});
class EventsList extends Component {
constructor(props) {
super(props);
this.state = { events: [] };
}
componentDidMount() {
axios
.get("http://localhost:9000/events/")
.then((response) => {
this.setState({ events: response.data });
})
.catch(function (error) {
console.log(error);
});
}
render() {
return (
<div className={classes.root}>
<GridList cellHeight={180} className={classes.gridList}>
<GridListTile key="Subheader" cols={2} style={{ height: "auto" }}>
<ListSubheader component="div">December</ListSubheader>
</GridListTile>
{this.state.events.map((tile) => (
<GridListTile key={tile.img}>
<img src={tile.img} alt={tile.title} />
<GridListTileBar
title={tile.title}
subtitle={<span>by: {tile.author}</span>}
actionIcon={
<IconButton
aria-label={`info about ${tile.title}`}
className={classes.icon}
></IconButton>
}
/>
</GridListTile>
))}
</GridList>
</div>
);
}
}
export default withStyles(styles)(EventsList);
Well, it is pretty much what the error says. Hooks can be used only with functional components. EventsList is a class component and you are trying to use makeStyles in it.
I faced the same issue, but I noticed that terminal was showing a "compiled successfully" message, and still the browser gave me this error.
I actually installed the material-ui/icons as: sudo npm install -g #material-ui/icons
( I thought I'll install it globally as an administrator so I will not have to install material-ui, every time on different projects/react apps)
Inside the react app I was working, I just ran ( npm install #material-ui/icons ) which updated the node_modules folder inside my react app, and the error was gone and everything was working fine on the browser as well.
Solution: just run "npm install #material-ui/core" and "npm install #material-ui/icons" on the terminal, being in the react app directory your'e working in. Hopefully, everything will get fixed.

Importing Express while trying to connect front-end(React) and back-end(Node.js)

I'm really new to js and I'm trying to build a full-stack web app. I've built most of the front-end React code and my back-end file has the connection and query to the db.
I'm trying to connect both of those files together, but as soon as i try to import 'express' in any of the files, it breaks. Without importing express it works alright.
Giving me this error on the browser when it runs: "TypeError: Unable to get property 'prototype' of undefined or null reference"
Index.js (trying to import Express here)
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
// import './index.css';
// var express = require('express')
// var app = express()
var Connection = require('tedious').Connection;
var Request = require('tedious').Request;
// const axios = require('axios')
ReactDOM.render(<App />, document.getElementById('root'));
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers:
serviceWorker.unregister();
App.js (front-end)
import React from 'react';
import TextField from '#material-ui/core/TextField';
import Button from '#material-ui/core/Button';
import Box from '#material-ui/core/Box';
import { createMuiTheme } from '#material-ui/core/styles';
import { ThemeProvider } from '#material-ui/styles';
import { Typography } from '#material-ui/core';
// var express = require('express')
// var app = express()
//change the primary colours of the UI
const theme = createMuiTheme({
palette: {
primary: {
main: '#00a843',
background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)',
},
},
});
export default class App extends React.Component
{
constructor(props) {
super(props);
this.handleEnterClick = this.handleEnterClick.bind(this);
this.handleSaveClick = this.handleSaveClick.bind(this);
this.state = {showAll: false, inputEmail: "", successfullySaved: true, newList: ""};
}
async handleEnterClick() {
//send the entered email to the server
// var xhr = new XMLHttpRequest()
// get a callback when the server responds
// xhr.addEventListener('load', () => {
// update the state of the component with the result here
// console.log(xhr.responseText)
// })
// open the request with the verb and the url
// xhr.open('PUT', '/api/controllers/AppController/enter')
// send the request
// xhr.send(JSON.stringify({ yourEmail: this.state.inputEmail }))
/*
const response = await fetch('/api/controllers/AppController/enter', {
method: 'PUT',
body: JSON.stringify({ email: this.state.inputEmail }),
})
console.log(await response.json())
*/
//update the UI to reflect the button being pressed
this.setState({showAll: true});
}
handleSaveClick() {
//save to the datbase
var xhr = new XMLHttpRequest()
// get a callback when the server responds
xhr.addEventListener('load', () => {
// update the state of the component with the result here
console.log(xhr.responseText)
})
// open the request with the verb and the url
xhr.open('PUT', '/api/controllers/AppController/save')
// send the request
xhr.send(JSON.stringify({ newList: this.state.newList }))
//update the UI to reflect the save
this.setState({showAll: false, inputEmail: "", successfullySaved: true, newList: ""});
//add a successful save message
}
render () {
return (
<form display="flex" noValidate autoComplete="off">
<ThemeProvider theme={theme}>
<div align = 'center'>
<TextField
id="tfInputEmail"
value={this.state.inputEmail}
onKeyPress={(ev) => {
if (ev.key === 'Enter') {
this.setState({showAll: true});
ev.preventDefault();
}
}}
onChange={e => this.setState({ inputEmail: e.target.value })}
style={{ width: 600}}
placeholder="first_last"
autoComplete = "email"
InputLabelProps={{
shrink: true,
style: {fontSize: 17, fontFamily: "Helvetica"}
}}
inputProps={{
style: {fontFamily: "Helvetica"}
}}
variant="outlined"
/>
<br/>
<Button id="btnEnter" variant="contained" color="primary"
style={{ marginTop: 15, marginBottom: 35, width: 600, height: 35}} onClick={this.handleEnterClick}>
Enter
</Button>
<PressedEnter show={this.state.showAll} click={this.handleSaveClick} list={this.state.newList}/>
</div>
</ThemeProvider>
</form>
);
}
}
function PressedEnter(props)
{
if(!props.show) {
return null;
}
return (
<div >
<Box fontSize={18} fontFamily="Helvetica" marginLeft="9px"
marginBottom="20px" marginTop="30px">
Check spelling and formatting before clicking 'Update your list' below. There's no error checking at the moment.
</Box>
<div width="100%" horizontal layout >
{
// REPLACE THE ABOVE DIV WITH A GRID LAYOUT FROM MATERIAL UI
}
{// Vertical layout for the textbox and its label
}
<div>
<Box fontSize={16} fontFamily="Helvetica"
marginBottom="10px" marginTop="20px">
Add/change/delete emails and separate by semicolon (;) here:
</Box>
<TextField
id="tfChangeList"
multiline
style={{ margin: 8, width: 446}}
InputLabelProps={{
shrink: true,
style: {fontSize: 20, fontFamily: "Helvetica"}
}}
inputProps={{
style: {height:300, fontFamily: "Helvetica"}
}}
variant="outlined"
/>
</div>
{// Vertical layout for the textbox and its label
}
<div>
<Box fontSize={16} fontFamily="Helvetica"
marginBottom="10px" marginTop="20px">
View your current Pulse Check list here:
</Box>
<TextField
disabled
id="tfCurrentList"
multiline
style={{ margin: 8, width: 446}}
InputLabelProps={{
shrink: true,
style: {fontSize: 20, fontFamily: "Helvetica"}
}}
inputProps={{
style: {height:300, fontFamily: "Helvetica"}
}}
variant="outlined"
/>
</div>
</div>
<br/>
<Button id="btnSave" variant="contained" color="primary" style={{ marginLeft: 8, marginBottom: 8,
marginTop: -8}} onClick={props.click}>
Save your Updates!
</Button>
</div>
);
}
);
}
Your full-stack web app should run both the client and server individually - i.e. run your Express application on localhost:3000 (the back end) and send HTTP requests to it from your client (React) running in a separate webpack server (the front end).
Because an application is "full-stack", this doesn't mean that the front and back ends are combined. These are separate. Hope this helps.

Resources