I'm new to Reactjs and I am getting the "unexpected token error" in my first attempt to build a series of components.
My console reports this:
SyntaxError: http://localhost:3004/app.js: Unexpected token (14:11)
class AnnouncementList extends React.Component
{
render() {
^
return (
I got really frustrated when searching the console output on Google it really messes up when we insert code in the search keywords. I have the babel plugin set up.
class AnnouncementsDashboard extends React.Component
{
render() {
return (
<div>
<AnnouncementList/>
<div>
);
}
}
class AnnouncementList extends React.Component
{
render() {
return (
<div>
<Announcement />
</div>
);
}
}
class Announcement extends React.Component
{
render(){
return (
<div></div>
);
}
}
/**
* #jsx React.DOM
*/
ReactDOM.render(<AnnouncementDashboard />, document.getElementById('container'));
updated, html included.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<!-- Disable browser cache -->
<meta http-equiv="cache-control" content="max-age=0" />
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="expires" content="0" />
<meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
<meta http-equiv="pragma" content="no-cache" />
<title>Project Two: Timers</title>
<link rel="stylesheet" href="vendor/semantic-ui/semantic.min.css" />
<link rel="stylesheet" href="style.css" />
<script src="vendor/babel-core-5.8.25.js"></script>
<script src="vendor/react.js"></script>
<script src="vendor/react-dom.js"></script>
<script src="vendor/uuid.js"></script>
<script src="vendor/fetch.js"></script>
</head>
<body>
<div id="main" class="main ui">
<h1 class="ui dividing centered header">Timers</h1>
<div id="container"></div>
</div>
<script type="text/babel" src="./client.js"></script>
<script type="text/babel" src="./helpers.js"></script>
<script type="text/babel" data-plugins="transform-class-properties" src="./app.js"></script>
</body>
</html>
Adding a scenario that works:
/* eslint-disable react/prefer-stateless-function */
/* eslint-disable react/jsx-boolean-value */
class AnnouncementDashboard extends React.Component
{
render() {
return (<div>"I'm am React, when something goes wrong I always say - unexpected token" </div>);
}
}
ReactDOM.render(<AnnouncementDashboard/>, document.getElementById('container'));
the only issue I see is the AnnouncementsDashboard component is missing a closing slash on the container div. Also I would restructure the code to use stateless functions. Unless you plan on adding state to them later on.
const Announcement = () => {
return (
<div></div>
);
}
const AnnouncementList = () => {
return (
<div>
<Announcement />
</div>
);
}
const AnnouncementsDashboard = () => {
return (
<div>
<AnnouncementList/>
</div>
);
}
Related
I have updated this to use react-helmet-async in place of react-helmet.
I have a React application that has implemented server side rendering. I am following the steps on this site: Documentation for react-helmet-async, to implement the react-helmet-async functionality to dynamically assign meta and title. I am using a provider and have added the Helmet component to the App.js and the learnerSetupContainer.js scripts. When I look at the source code for both these pages I can that the title and meta for the home page is properly updated but the learnerSetupContainer is not being updated and is showing the same title and meta as the home page,
<title data-rh="true" itemprop="name" lang="en">Welcome to our Homepage</title>
<meta data-rh="true" name="description" content="Teach Learn Game"/><meta data-rh="true" name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no"/>
I see other stackoverflow questions that say, "It's not documented in the readme, but you have to add data-react-helmet="true" to your meta tags that you want to replace with react-helmet." I tried adding this string but there was no change. Maybe I am not adding correctly. Can anyone see what I am doing wrong?
Below is the code I am using:
template.js
export default ({ markup, helmet , css }) => {
return `<!doctype html>
<html ${helmet.htmlAttributes.toString()}>
<head>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-1234567-9">
</script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-123456789-9');
</script>
<script data-ad-client="ca-pub-123456789012345" async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<meta charset="utf-8">
<meta name="msvalidate.01" content="1234567890ASDFGHJJ" />
<meta name="google-site-verification" content="1234567890ASDFGHJKL" />
${helmet.title.toString()}
${helmet.meta.toString()}
${helmet.link.toString()}
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400">
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<style>
a{
text-decoration: none;
color: #bb4d00
}
</style>
</head>
<body ${helmet.bodyAttributes.toString()}>
<div id="root">${markup}</div>
<style id="jss-server-side">${css}</style>
<script type="text/javascript" src="/dist/bundle.js"></script>
</body>
</html>`;
};
express.js (only code relevant to react-helmet)
import {Helmet, HelmetProvider} from "react-helmet-async";
app.get("*", (req, res) => {
const sheets = new ServerStyleSheets();
const context = {};
const helmetContext = {};
const markup = ReactDOMServer.renderToString(
//const markup = ReactDOMServer.renderToStaticMarkup(
sheets.collect(
<StaticRouter location={req.url} context={context}>
<ThemeProvider theme={theme}>
<HelmetProvider context = {helmetContext}>
<MainRouter />
</HelmetProvider>
</ThemeProvider>
</StaticRouter>
)
);
const {helmet} = helmetContext;
console.log ("Express - markup = ", markup);
console.log ("Express - helmet = ", helmet);
console.log ("Express - helmetContext = ", helmetContext);
console.log ("Express - helmet.title.toString() = ", helmet.title.toString());
console.log ("Express - helmet.meta.toString() = ", helmet.meta.toString());
if (context.url) {
return res.redirect(303, context.url);
}
const css = sheets.toString();
res.status(200).send(
Template({
markup: markup,
helmet: helmet,
css: css,
})
);
});
App.js (only code relevant to react-helmet)
import {Helmet, HelmetProvider} from "react-helmet-async";
return (
<>
<React.StrictMode>
<BrowserRouter>
<ThemeProvider theme={responsivetheme}>
<SpeechDataProvider>
<CriteriaProvider>
<RandomOptionsProvider>
<HelmetProvider>
<MainRouter />
</HelmetProvider>
</RandomOptionsProvider>
</CriteriaProvider>
</SpeechDataProvider>
</ThemeProvider>
</BrowserRouter>
</React.StrictMode>
</>
);
MenuRouter.js (only code relevant to react-helmet)
import {Helmet, HelmetProvider} from "react-helmet-async";
return (
<div>
<Helmet
data-rh="true"
htmlAttributes={{lang: "en", amp: undefined}} // amp takes no value
//titleTemplate="%s | React App"
titleAttributes={{itemprop: "name", lang: "en"}}
title="Welcome to our Homepage"
meta={[
{name: "description", content: "Teach Learn Game"},
{name: "viewport", content: "minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no"},
]}
/>
</div>
learnerSetupContainer.js (only code relevant to react-helmet)
import {Helmet, HelmetProvider} from "react-helmet-async";
return (
<>
<div>
<Helmet>
<title data-rh="true">Welcome to our Learner Setup Page </title>
<meta data-rh="true" name="description" content="Game Options: Vocabulary, Math, History and Geography" />
<meta data-rh="true" name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no" />
</Helmet>
</div>
</>
I have the following 'List' component where I'm trying to update this.state from props. I can't seem to get getDrivedStateFromProps to work correctly with componentDidUpdate. There's a problem with the logic but it doesn't seem that gDSFC ever fires as I get the same response whether it's commented out or not.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>list</title>
<script src="react/react.js"></script>
<script src="react/react-dom.js"></script>
<script src="https://unpkg.com/babel-standalone#6.15.0/babel.min.js"></script>
</head>
<body>
<div id='container'>
</div>
</body>
</html>
<script type = 'text/jsx'>
class FilteredList extends React.Component{
constructor(props){
super(props);
this.state={list:this.props.list};
}
filter(input){
var newList = this.state.list.filter(function(item){
return (item.search(input.target.value)!=-1);
});
this.setState({list:newList});
}
render(){
return(
<div>
<input type='text' placeholder='Filter' onChange={this.filter.bind(this)} />
<List items={this.state.list} />
</div>
);
}
}
class List extends React.Component{
constructor(props){
super(props);
this.state={items:this.props.items};
}
static getDerivedStateFromProps(nextProps, prevState) {
console.log('hello1');
if (nextProps.items !== prevState.items) {
return {
items: nextProps.items,
};
}
// Return null if the state hasn't changed
return null;
}
componentDidUpdate(nextProps,prevState){
console.log('hello2');
if(nextProps.items !== prevState.items)
this.setState({items:nextProps.items});
}
render(){
return(
<ul>
{this.state.items.map(function(item){
return(<li key={item}>{item}</li>);
})}
</ul>
);
}
}
ReactDOM.render(
<div><FilteredList list={['anteater','bear','cat','dog','elephant','fox']} /></div>,
document.getElementById('container')
);
</script>
Upgrade to v5.2.1 or higher and this open issue should be fixed
yarn upgrade -L react-helmet
I think you need 16.3.1 or later, possibly 16.3.3
I have a page where I want to test some react code. Both scripts are working independently, if they are alone in the page. If I add both, the script with jsx does not work. Is there an explanation for that behavior? Is it not allowed?
There is nothing about the code. I am guessing the imports cannot live together.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="index.css">
<title>My Website</title>
</head>
<body>
<div id="myroot"></div>
<div id="myBabel"></div>
<script src="https://unpkg.com/react#16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom#16/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone#6/babel.min.js"></script>
<!-- Load our React component. -->
<script src="js/index2.js"></script>
<script type="text/babel" src="js/index.jsx"></script>
</body>
</html>
Here the index2.js contents:
class App extends React.Component {
render() {
return React.createElement("div", null, React.createElement("h1", null, " the list "));
}
}
ReactDOM.render(React.createElement(App,null,null),
document.getElementById("myroot"));
And here a React with jsx:
class App extends React.Component {
state = {
/* Initial State */
input: "",
reversedText: ""
};
/* handleChange() function to set a new state for input */
handleChange = event => {
const value = event.target.value;
this.setState({
input: value
});
};
/* handleReverse() function to reverse the input and set that as new state for reversedText*/
handleReverse = event => {
event.preventDefault();
const text = this.state.input;
this.setState({
reversedText: text
.split("")
.reverse()
.join("")
});
};
render() {
return (
<React.Fragment>
{ /* handleReverse() is called when the form is submitted */}
<form onSubmit={this.handleReverse}>
<div>
{ /* Render input entered */}
<label>Text: {this.state.input}</label>
</div>
<div>
{ /* handleChange() is triggered when text is entered */ }
<input
type="text"
value={this.state.input}
onChange={this.handleChange}
placeholder="Enter a text"
/>
</div>
<div>
<button>Reverse Text</button>
</div>
</form>
{ /* Render reversed text */}
<p>Reversed Text: {this.state.reversedText}</p>
</React.Fragment>
);
}
}
ReactDOM.render(<App />, document.getElementById("myBabel"));
Like I said, the imports are working alone but both at the same time in the HTML page are not.
class List extends React.Component {
render() {
return React.createElement("div", null, React.createElement("h1", null, " the list "));
}
}
ReactDOM.render(React.createElement(List,null,null),
document.getElementById("myroot"));
If you check the console logs for your code you will find this error -
Uncaught SyntaxError: Identifier 'App' has already been declared.
You have both your components identified as App. So React needs different identifiers to keep track of each component. I changed one of the class name from App to List. This will work. Make sure to name your components.
I wonder if we can add multiple react components into HTML without having the related files usually downloaded with npm, or added to a normal HTML but we add a certain component for a chat app as my attempt here, here is a long example:
<html lang="en">
<head>
<script src="https://unpkg.com/babel-standalone#6/babel.min.js"></script>
<script crossorigin src="https://unpkg.com/react#16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
</head>
<body>
<div id="app"></div>
<script type="text/babel">
class App extends React.Component{
state={
messages:[
{ }
],
userId:''
}
addMessage=(message)=>{
message.num = Math.random();
message.id=this.state.messages.id;
let messages = [...this.state.messages, message];
this.setState({
messages })
}
addId=(userId)=>{
this.setState({
userId
})
}
render() {
return (
<div className="appContainer">
<User userId={this.addId} />
<TopSection Users={this.state.userId}/>
<Messages userId = {this.state.userId} messages={this.state.messages}/>
<AddMessage addMessage={this.addMessage} />
</div>
);
}
}
}
const Messages = ({messages, userId}) =>{
const messageList= (messages.length)? (messages.slice(1).map(message=>{
return(
<div className="message" key={message.num}>
<span key={userId.num}>{message.content?(userId):(null)}</span>
<p>{message.content}</p>
</div>
)
})) : (null);
return(
<div className="textContainer">
{messageList}
</div>
)
}
ReactDOM.render(<App />, document.getElementById('app'));
</script>
</body>
</html>
please let me know if there is away to get this to work.
You mean add components to different dom nodes ?
import {render} from 'reactDOM'
import React from 'react'
import AppOne from './appOne'
import AppTwo from './appTwo'
render(<AppOne />, document.getElementById('appOne'));
render(<AppTwo />, document.getElementById('appTwo'));
React v16 has portals as well for adding componnets to differnt parts of the dom tree
I tried to do the server side render using renderToString method.
function handleRender(req, res) {
const html = renderToString(
<Counter />
);
res.send(renderFullPage(html));
}
function renderFullPage(html) {
return `
<!doctype html>
<html>
<head>
<title>React Universal Example</title>
</head>
<body>
<div id="app">${html}</div>
<script src="/static/bundle.js"></script>
</body>
</html>
`
}
If the component like following it works:
Counter.js
const Counter = () => {
function testClick(){
console.log('test');
}
return (
<div>
<div onClick={testClick.bind(this)}>
test
</div>
</div>
);
};
export default Counter;
However, if I change Counter.js into following:
class Counter extends React.Component {
testClick(){
console.log('click');
}
render() {
return (
<div>
<div onClick={this.testClick.bind(this)}>
test btn
</div>
</div>
)
}
}
export default Counter;
It will show errors:
Uncaught Error: locals[0] does not appear to be a `module` object with Hot Module replacement API enabled. You should disable react-transform-hmr in production by using `env` section in Babel configuration.
So how to use React.Component with renderToString method?
I minimize the project and push to Github. Please have a look.
https://github.com/ovojhking/ssrTest/tree/master