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

`×
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.

Related

delete from firebase real time database

it makes a flat list of rooms and inside those rooms are messages. So I want to long press on a specific room in the list, and when i do this, I want to delete a room.
onLongPress={() => this.roomsRef.remove({item})}
I thought the above would work, but it fails. I put it in the render row part. It comes up saying Reference.remove failed. first argument must be a valid function. Like inside these rooms it has messages and I think thats where im going wrong but im not sure how to go about it. thank you
'use strict'
import React, { Component, useEffect } from 'react';
import { Text, Image, TextInput, TouchableHighlight, StatusBar, FlatList, View, TouchableOpacity, Dimensions, LogBox, Alert } from 'react-native';
// import firebaseApp from './firebaseConfig.js';
import firebaseApp from '../config/firebasekeys';
import {SafeAreaView} from 'react-native-safe-area-context'
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view'
import {Avatar} from 'react-native-elements'
import { color } from 'react-native-reanimated';
const DeviceHeight = Dimensions.get('screen').height
const DeviceWidth = Dimensions.get('screen').width
class Rooms extends Component {
static navigationOptions = {
title: 'Rooms',
};
constructor(props) {
super(props);
var firebaseDB = firebaseApp.database();
this.roomsRef = firebaseDB.ref('rooms'); // rooms collection
this.state = {
rooms: [],
newRoom: ''
}
}
// maybe its this.roomsRef.remove(item.name) or maybe its name idk hmmm
componentDidMount() {
LogBox.ignoreLogs(['VirtualizedLists should never be nested']); // doing this to ignore the log box error for scroll view
this.listenForRooms(this.roomsRef);
}
listenForRooms(roomsRef) {
roomsRef.on('value', (dataSnapshot) => {
var roomsFB = [];
dataSnapshot.forEach((child) => {
roomsFB.push({
name: child.val().name,
key: child.key
});
});
this.setState({ rooms: roomsFB });
});
}
addRoom() {
if (this.state.newRoom === '') {
return
}
this.roomsRef.push({ name: this.state.newRoom });
this.setState({ newRoom: '' });
}
openMessages(room) {
this.props.navigation.navigate("Messages", {roomKey: room.key, roomName: room.name});
}
renderRow(item) {
return (
<TouchableOpacity
onPress={() => this.openMessages(item)}
onLongPress={() => this.roomsRef.remove({name:item})}
>
<Text style={{
color: 'orange',
fontSize: 22,
}}>{item.name}</Text>
</TouchableOpacity>
)
}
render() {
return (
<SafeAreaView style={styles.container}>
<StatusBar style="auto"/>
<KeyboardAwareScrollView>
<View>
<View >
<TextInput>
}}
placeholder={"enter chat name"}
onChangeText={(text) => this.setState({newRoom: text})}
value={this.state.newRoom}
/>
<TouchableHighlight
style={{
marginRight: 20
}}
onPress={() => this.addRoom()}
>
>
</TouchableHighlight>
</View>
<View>
<FlatList
data={this.state.rooms}
renderItem={({item}) => (this.renderRow(item)
)}
/>
</View>
{/* <View>
<FlatList
data={this.state.rooms}
renderItem={({item}) => (this.renderRow(item)
)}
/>
</View> */}
</View>
</KeyboardAwareScrollView>
</SafeAreaView>
);
}
}
export default Rooms;
I recommend keeping the reference docs for the API handy as you're developing, as there are quite a few problems you can catch that way. For example, the Reference.remove() method doesn't take an item as its argument (in fact: it typically is called without arguments).
To delete a specific node, you should build a reference to that node, and then call remove() on the reference:
roomsRef.child("keyOfRoomToRemove").remove()

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).

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.

How can I modify this code so that render waits for Promise Items?

I am new to React and I load all the data from my database initially on page load but there is info I need to find in an array and apparently it isn't instant. What do I need to do to make sure the render method only renders the objects when the object promises have resolved?
I haven't tried much... I'm really stuck here.
This seems different than the other problems I've read here because I load a bunch on info in the beginning just fine but I need to call some team information every time a function is called so it isn't as simple as loading it once because the object i need is always different.
This code is the main issue. I also included the full file below:
I did some modification to the code in a edit: I realized that I just need to call the opponent team because I have the player team already.
if (team.id === game.team_1) {
var redTeam = team;
// set blueTeam based on game.team_1
// firebase.teams().doc('teams/{game.team_2}')
} else {
var blueTeam = team;
// set redTeam based on game.team_1
// firebase.teams().doc('teams/{game.team_1}')
}
Full file:
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import Async from 'react-promise'
import { withFirebase } from '../Firebase';
// import * as ROUTES from '../../constants/routes';
import { Container, Image, Spinner, Col, Row, Card, Accordion, Button } from 'react-bootstrap'
class PlayerGameList extends Component {
constructor(props) {
super(props);
this.state = {
loadingTeams: false,
loadingSchedule: false,
teams: [],
schedule: []
};
}
componentDidMount() {
this.setState({
loadingTeams: true,
loadingSchedule: true,
});
this.unsubscribe = this.props.firebase
.teams()
.where('players', 'array-contains', '-LXkkB7GNvYrU4UkUMle')
.onSnapshot(snapshot => {
let teams = [];
snapshot.forEach(doc =>
teams.push({ ...doc.data(), uid: doc.id }),
);
this.setState({
teams,
loadingTeams: false,
});
});
this.unsubscribe2 = this.props.firebase
.schedule()
.onSnapshot(snap => {
let schedule = [];
snap.forEach(doc =>
schedule.push({ ...doc.data(), uid: doc.id }),
);
this.setState({
schedule,
loadingSchedule: false,
});
});
}
componentWillUnmount() {
this.unsubscribe();
this.unsubscribe2();
}
render() {
const { teams, schedule, loadingTeams, loadingSchedule } = this.state;
return (
<div>
<h2>Games</h2>
{loadingTeams && loadingSchedule && <div colSpan="12"><Spinner animation="border" role="status">
<span className="sr-only">Loading...</span>
</Spinner></div>}
{/* CONTENT */}
<Container fluid>
<Row>
{getTeams({ teams, schedule })}
</Row>
</Container>
</div >
);
}
}
function getTeams({ teams, schedule }) {
if (!teams) {
return null;
}
if (!teams.length) {
return null;
} else {
return teams.map(team => getGames({ team, schedule }))
}
}
function getGames({ team, schedule }) {
schedule.sort((a, b) => (a.time > b.time) ? -1 : 1)
if (!schedule) {
return null;
}
if (!schedule.length) {
return null;
} else {
return schedule.map(game => guts({ team, game }));
}
}
function guts({ team, game }) {
const image = {
height: '25px',
width: '25px'
}
if (team.id === game.team_1) {
var redTeam = team;
// set blueTeam based on game.team_1
// firebase.teams().doc('teams/{game.team_2}')
} else {
var blueTeam = team;
// set redTeam based on game.team_1
// firebase.teams().doc('teams/{game.team_1}')
}
if (game.team_1 === team.id || game.team_2 === team.id) {
var time = new Date(game.time.seconds * 1000);
var dateFormat = require('dateformat');
var finalTime = dateFormat(time, 'ddd mmm dd, h:MM tt')
return (
<Col lg='4' md='6' sm='12' key={game.uid} style={{ marginBottom: '15px' }}>
<Card>
<Card.Body>
<Row>
<Image src={team.logo} style={image} roundedCircle />
<p>{team.name}</p>
<div style={{ height: '25px', width: '25px', backgroundColor: 'red' }}></div>
</Row>
<Row>
<Image src={team.logo} style={image} roundedCircle />
<p>{team.name}</p>
<div style={{ height: '25px', width: '25px', backgroundColor: 'blue' }}></div>
</Row>
<Row>
<div>
{finalTime}
</div>
</Row>
</Card.Body>
<Accordion>
<Card style={{ margin: '0', padding: '0' }}>
<Card.Header>
<Accordion.Toggle as={Button} variant="link" eventKey="0">
Show Match IDs
</Accordion.Toggle>
</Card.Header>
<Accordion.Collapse eventKey="0">
<Card.Body>{game.match_id}</Card.Body>
</Accordion.Collapse>
</Card>
</Accordion>
</Card>
</Col>
);
}
}
export default withFirebase(PlayerGameList);
The items all load blank then a few seconds later all the console logs come through with the array objects. When I tell it to await the program just throws an error.

Fetch a variable from node_modules

I am trying to fetch a variable from node_modules to my application. I have exported it with module.exports, but when I use require('path/of/required/file/in/node_modules') it is showing 'unexpected token import'. I am trying to get the user info from node_modules since there is no official strategy for keystone to fetch the user data.
My local file
var keystone = require('keystone');
Teaching = keystone.list('teaching');
UserInfo = require('../../node_modules/keystone/admin/client/App/components/Footer/index.js').footer;
User = keystone.list(keystone.get('user model'));
console.log(User);
exports = module.exports =function(req,res){
var view = new keystone.View(req,res);
var locals = res.locals;
locals.section = 'teaching';
locals.data = {
teachingData : []
};
view.on('init',function(next){
var teaching = Teaching.model.find();
teaching.exec(function(err,results){
locals.data.teachingData = results;
//console.log(locals.data.teachingData);
next(err);
});
});
view.render('teaching');
}
Node_module file
import React from 'react';
import { css, StyleSheet } from 'aphrodite/no-important';
import { Container } from '../../elemental';
import theme from '../../../theme';
var Footer = React.createClass({
displayName: 'Footer',
propTypes: {
appversion: React.PropTypes.string,
backUrl: React.PropTypes.string,
brand: React.PropTypes.string,
user: React.PropTypes.object,
User: React.PropTypes.object, // eslint-disable-line react/sort-prop-types
version: React.PropTypes.string,
},
// Render the user
renderUser () {
const { User, user } = this.props;
if (!user) return null;
return (
<span>
<span> Signed in as </span>
<a href={`${Keystone.adminPath}/${User.path}/${user.id}`} tabIndex="-1" className={css(classes.link)}>
{user.name}
</a>
<span>.</span>
</span>
);
},
render () {
const { backUrl, brand, appversion, version } = this.props;
return (
<footer className={css(classes.footer)} data-keystone-footer>
<Container>
<a
href={backUrl}
tabIndex="-1"
className={css(classes.link)}
>
{brand + (appversion ? (' ' + appversion) : '')}
</a>
<span> powered by </span>
<a
href=""
target="_blank"
className={css(classes.link)}
tabIndex="-1"
>
VK
</a>
<span> version {version}.</span>
{this.renderUser()}
</Container>
</footer>
);
},
});
/* eslint quote-props: ["error", "as-needed"] */
const linkHoverAndFocus = {
color: theme.color.gray60,
outline: 'none',
};
const classes = StyleSheet.create({
footer: {
boxShadow: '0 -1px 0 rgba(0, 0, 0, 0.1)',
color: theme.color.gray40,
fontSize: theme.font.size.small,
paddingBottom: 30,
paddingTop: 40,
textAlign: 'center',
},
link: {
color: theme.color.gray60,
':hover': linkHoverAndFocus,
':focus': linkHoverAndFocus,
},
});
exports.footer = Footer.renderUser();
1) The "Unexpected token import" error is probably occuring because the current JavaScript environment does not support the import statement; the code you are trying to import from the Keystone node module is transpiled before it gets used normally. When Keystone uses that component, it's not an issue. But if you're importing a React component into a non-React file, you're bound to have problems. Which leads to my next question:
2) UserInfo isn't used in your code at all. You can't just use Keystone's React component for showing user information, unless you are working in a React environment (which it does not look like you are.) What is your use case for using this component?

Resources