I am new to React. I have downloaded and installed code from this "CSS Modules and React" tutorial:-
Tutorial: https://css-tricks.com/css-modules-part-3-react/
Code: https://github.com/robinrendle/react-css-modules-boilerplate
The downloaded code is basically working as far as I can tell but I'm unable to get simple onClick events working inside Components.
I've tried all suggestions I can find on internet but none of the solutions have worked for me. Could you please help me get this working. Thank you.
package.json:-
{
"name": "css-tricks-modules",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "webpack-dev-server --progress --colors",
"start": "webpack && npm run dev"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"babel-core": "^6.7.4",
"babel-loader": "^6.2.4",
"babel-preset-es2015": "^6.6.0",
"babel-preset-react": "^6.5.0",
"browser-sync": "^2.12.8",
"browser-sync-webpack-plugin": "^1.0.1",
"css-loader": "^0.23.1",
"extract-text-webpack-plugin": "^1.0.1",
"react": "^15.0.2",
"react-dom": "^15.0.2",
"react-router": "^2.4.0",
"static-site-generator-webpack-plugin": "^2.0.1",
"webpack": "^1.12.14",
"webpack-dev-server": "^1.14.1"
},
"dependencies": ""
}
webpack.config.js:-
var ExtractTextPlugin = require('extract-text-webpack-plugin'),
StaticSiteGeneratorPlugin = require('static-site-generator-webpack-plugin'),
BrowserSyncPlugin = require('browser-sync-webpack-plugin'),
data = require('./data.js'),
path = require('path');
module.exports = {
entry: './src/router',
output: {
path: './build',
filename: 'bundle.js',
libraryTarget: 'umd',
publicPath: '/'
},
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel',
// include: __dirname + '/src',
include: path.join(__dirname,'src'),
},
{
test: /\.css$/,
loader: ExtractTextPlugin.extract('css?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]'),
// include: __dirname + '/src'
include: path.join(__dirname,'src')
}
],
},
plugins: [
new ExtractTextPlugin("styles.css"),
new StaticSiteGeneratorPlugin('main', data.routes, data),
new BrowserSyncPlugin({
host: 'localhost',
port: 3000,
proxy: 'http://localhost:8080/'
})
]
};
Home.js:-
import React from 'react'
import CoolButton from '../components/Button/Button'
import Counter from '../components/counter'
import App from '../components/app'
import App2 from '../components/app2'
import SayHello from '../components/sayHello'
export default class Home extends React.Component {
render() {
return (
<div>
<h1>Home page</h1>
<p>This is a home page</p>
<App />
<App2 />
<SayHello />
<CoolButton text='A super cool button'/>
</div>
)
}
}
sayHello.js (onClick event is not working):-
import React from 'react'
export default class SayHello extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
console.log("Hello!!!");
alert("Hello!!!!");
}
render() {
return (
<button onClick={this.handleClick}>
Say hello
</button>
);
}
}
app.js (onClick event not working):-
import React from 'react'
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
data: 'Initial data...'
}
this.updateState = this.updateState.bind(this);
};
updateState() {
this.setState({data: 'Data updated!!!'})
}
render() {
return (
<div>
<button onClick = {this.updateState}>CLICK</button>
<h4>{this.state.data}</h4>
</div>
);
}
}
app2.js (onClick event not working):-
import React from 'react';
export default class App2 extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// This binding is necessary to make `this` work in the callback
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn
}));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
The code compiles without errors and in Components "SayHello" and "App2" their initial state text is rendered but their onClick event isn't occurring or the data isn't updating. I think most likely the event isn't firing but I'm not sure.
I'd much appreciate advice on where/why the problem is occurring and how to fix. Thanks.
Related
We're developing a dashboard React-application in which other (trusted) developers can create their own React-widgets in separate environments. The goal would be a situation where new widgets wouldn't require updation to the dashboard-application and instead, these external React-components could be loaded at runtime.
So developer A would have his own project, where he would bundle a React-component into a js-file, which would be forwarded to a hosting site, S3 for example where the dashboard application could read them via a string, at runtime.
For example a weather-widget:
import React, {useState} from "react";
function Weather() {
const [city, setCity] = useState("city");
const weatherUri = `https://wttr.in/${city}_tqp0.png`;
return (
<div>
<input type="text" value={city} onChange={(e) => setCity(e.target.value)}/>
<div>
<img src={weatherUri} alt={city}/>
</div>
</div>
);
}
export default Weather;
This could be then imported to the dashboard-application. I've understood that React's dynamic code-splitting with dynamic url would work here. Either via a situation where widget would have its own React-library, or it'd get it from the dashboard-application. We've, in fact, made this to work, but as soon as we add a state to the component, it breaks:
Uncaught TypeError: Cannot read properties of null (reading 'useState')
at Object.useState (react.development.js:1612:23)
at Weather (weather_widget.js:36:33)
We've configured the widget-component's configuration as follows (React-library will be imported from the dashboard-application):
// ====== vite.config.js ========== (widget)
export default defineConfig({
plugins: [react()],
define: {
'process.env': {}
},
build: {
lib: {
entry: 'src/lib/Weather.tsx',
name: 'Weather',
fileName: 'weather',
formats: ['es']
},
rollupOptions: {
plugins: [
externalGlobals({
react: "React"
})
],
external: ['react'],
output: {
globals:{
react: 'React'
}
}
}
},
})
// ===== package.json ===== (widget)
{
"name": "weather",
"private": true,
"version": "0.0.0",
"type": "module",
"files": [
"dist"
],
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview"
},
"dependencies": {
"react": "18.2.0",
"react-dom": "18.2.0",
"rollup-plugin-external-globals": "^0.6.1"
},
"devDependencies": {
"#types/node": "18.7.23",
"#types/react": "18.0.21",
"#types/react-dom": "^18.0.6",
"#vitejs/plugin-react": "^1.0.7",
"path": "^0.12.7",
"typescript": "^4.6.4",
"vite": "^2.8.0"
}
}
This is how we've tried to import it to the dashboard-application:
export const WidgetCard = (widgetId: string) => {
const WidgetComponent = React.lazy(() =>
import(`/path/to/${widgetId}.js`));
return
<>
<Suspense fallback={<Loading/>}>
<WidgetComponent/>
</Suspense>
</>
)
});
For the final product, the logic would be as follows:
User will generate a JS-bundle of their React-component
User will call some sort of API, which will save bundle to a hosting site and also add the new widget to a database of some sort.
I'm working on a React site with server-side rendering & Material-ui. Everything was working great including the mui JSS stuff.
Then I added an SVG icon from #material-ui/icons
Now, Edge & IE11 are complaining:
Warning: Prop d did not match. Server: "M 0 0 h 24 v 24 H 0 Z" Client: "M0 0h24v24H0z"
The warning indicates the server and client renderings don't match, but if I get the server rendering with curl it is correct and does NOT include the spaces shown in the IE/Edge console.
All other browsers are (of course) OK.
Has anyone else encountered SSR issues in MS browsers only?
This is as small as I can get an example. It's based on material-ui-master/examples/ssr with most stuff removed:
server.js:
import express from "express";
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import App from './App';
function renderFullPage(html) {
return `
<!doctype html>
<html>
<body>
<div id="root">${html}</div>
<script src="build/bundle.js"></script>
</body>
</html>
`;
}
function handleRender(req, res) {
// Render the component to a string.
const html = ReactDOMServer.renderToString(
<App />
);
res.send(renderFullPage(html));
}
const app = express();
app.use('/build', express.static('build'));
// This is fired every time the server-side receives a request.
app.use(handleRender);
const port = 3000;
app.listen(port);
client.js:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
class Main extends React.Component {
render() {
return <App />;
}
}
ReactDOM.hydrate(
<Main />
, document.querySelector('#root')
);
App.js:
import React from 'react';
import { Menu } from "#material-ui/icons";
export default class App extends React.Component {
render() {
return (
<Menu />
);
}
}
package.json:
{
"name": "ssr",
"version": "3.0.0",
"private": true,
"dependencies": {
"#babel/core": "latest",
"#babel/node": "latest",
"#babel/plugin-proposal-class-properties": "latest",
"#babel/preset-env": "^7.4.2",
"#babel/preset-react": "latest",
"#material-ui/core": "latest",
"#material-ui/icons": "^3.0.2",
"babel-loader": "next",
"express": "latest",
"fs": "0.0.1-security",
"net": "^1.0.2",
"nodemon": "latest",
"prop-types": "latest",
"react": "latest",
"react-dom": "latest",
"react-jss": "^8.1.0",
"webpack": "latest",
"webpack-cli": "latest"
},
"scripts": {
"start-server": "SET NODE_ENV=development& nodemon --inspect ./build/server.js",
"start": "webpack -w"
}
}
webpack.config.js:
const path = require('path');
const browserConfig = {
entry: './client.js',
node: {
fs: "empty"
},
mode: process.env.NODE_ENV || 'development',
output: {
path: path.resolve(__dirname, 'build'),
filename: 'bundle.js',
publicPath: '/',
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
},
],
},
};
const serverConfig = {
entry: './server.js',
target: 'node',
node: {
fs: "empty"
},
mode: process.env.NODE_ENV || 'development',
output: {
path: path.resolve(__dirname, 'build'),
filename: 'server.js',
publicPath: '/',
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
},
],
},
};
module.exports = [browserConfig, serverConfig]
.babel.rc:
{
"presets": ["#babel/preset-env", "#babel/preset-react"],
"plugins": ["#babel/plugin-proposal-class-properties"]
}
I had a similar issue. This isn't a problem with SSR, but with conditional rendering in your JSX where the condition differs on the server and the client.
In my case, I rendered something based on a condition read from localStorage, which was only defined on the client. On server, it returned undefined, so what was rendered on the client and the server did not match.
The solution in my case was to conditionally render based on whether the component rendered on the client.
I wrote the following custom hook:
import {useEffect, useState} from "react";
export const useLoaded = () => {
const [loaded, setLoaded] = useState(false);
useEffect(() => setLoaded(true), []);
return loaded;
};
I use it as such:
// in the functional component's body
const loaded = useLoaded();
// in the JSX
{localCondition && loaded &&
<MyComponent />
}
With class components you'd use the componentDidMount lifecycle method and setState instead.
I've had the same problem ...did not match Server: ... Client: ... using NextJS (React) with an Express.js server (node server.js).
The solution was to render the component only if process.browser is true.
{
process.browser ?
<MyComponent /> :
null
}
So this does appear to be a bug in React. I logged an issue to the Material-ui project which resulted in this open issue in React:
https://github.com/facebook/react/issues/15187
The warning seems to be benign and with Edge moving over to Chromium, I'm not as concerned as I once was.
I know this question may have been asked but am just frustrated. Reactjs marks = at the line of code below as unexpected token error
handleChange1 = {(selectedOption) => {
All the required dependency has been installed.
below is the entire code
import React, { Component } from 'react';
import { render } from 'react-dom';
import { Link } from 'react-router-dom';
import { connect } from 'react-redux';
import Hello from './Hello';
import Select from 'react-select'
//import './style.css';
import 'react-select/dist/react-select.css';
class Plans extends Component {
constructor() {
super();
this.state = {
name: 'React',
selectedOption: {},
selectedOption2: {}
};
}
handleChange1 = {(selectedOption) => {
this.setState({selectedOption});
}
};
handleChange2 = (selectedOption) => {
this.setState({selectedOption2: selectedOption})
}
render() {
const options1 = [
{value: 'one', label: 'One'},
{value: 'two', label: 'Two'}
];
const options2 = [
{value: 'one-a', label: 'One A', link: 'one'},
{value: 'one-b', label: 'One B', link: 'one'},
{value: 'two-a', label: 'Two A', link: 'two'},
{value: 'two-b', label: 'Two B', link: 'two'}
];
const filteredOptions = options2.filter((o) => o.link === this.state.selectedOption.value)
return (
<div>
<p>Select one first</p>
<Select
name="form-field-name"
value={this.state.selectedOption.value}
onChange={this.handleChange1}
options={options1}
/>
<p>Then the other</p>
<Select
name="form-field-name"
value={this.state.selectedOption2.value}
onChange={this.handleChange2}
options={filteredOptions}
/>
</div>
);
}
}
//render(<Plans />, document.getElementById('app'));
function mapStateToProps(state) {
}
const connectedPlans = connect(mapStateToProps)(Plans);
export { connectedPlans as Plans };
Here is my package.json
{
"name": "example",
"version": "1.0.0",
"repository": {
"type": "git",
"url": ""
},
"license": "MIT",
"scripts": {
"start": "webpack-dev-server --open"
},
"dependencies": {
"history": "^4.6.3",
"node-sass": "^4.9.4",
"react": "^16.0.0",
"react-dom": "^16.0.0",
"react-redux": "^5.0.5",
"react-router-dom": "^4.1.2",
"react-select": "^2.1.1",
"react-toastify": "^4.4.0",
"redux": "^3.7.2",
"redux-logger": "^3.0.6",
"redux-thunk": "^2.2.0"
},
"devDependencies": {
"babel-core": "^6.21.0",
"babel-loader": "^7.1.2",
"babel-preset-es2015": "^6.18.0",
"babel-preset-react": "^6.16.0",
"babel-preset-stage-3": "^6.24.1",
"css-loader": "^1.0.1",
"html-webpack-plugin": "^2.26.0",
"path": "^0.12.7",
"sass-loader": "^7.1.0",
"style-loader": "^0.23.1",
"webpack": "^3.6.0",
"webpack-dev-server": "^2.8.2"
}
}
Updates
App.jsx
import React from 'react';
import { Router, Route } from 'react-router-dom';
import { connect } from 'react-redux';
import { history } from '../_helpers';
import { alertActions } from '../_actions';
import { PrivateRoute } from '../_components';
import { Plans } from '../Plans';
class App extends React.Component {
constructor(props) {
super(props);
const { dispatch } = this.props;
history.listen((location, action) => {
// clear alert on location change
dispatch(alertActions.clear());
});
}
render() {
const { alert } = this.props;
return (
<div className="jumbotron">
<div className="container">
<div className="col-sm-8 col-sm-offset-2">
{alert.message &&
<div className={`alert ${alert.type}`}>{alert.message}</div>
}
<Router history={history}>
<div>
<Route path="/plans" component={Plans} />
</div>
</Router>
</div>
</div>
</div>
);
}
}
function mapStateToProps(state) {
const { alert } = state;
return {
alert
};
}
const connectedApp = connect(mapStateToProps)(App);
export { connectedApp as App };
How I solve the problem. First I implemented the solution powered by Dacre in the comments above. I then discovered that react-select.css' files is not in the node_modules so I re-install it again so as to enable me to import it..
I added this line of code below
render(<Plans />, document.getElementById('app'));
and then remove the code below
function mapStateToProps(state) {
}
const connectedPlans = connect(mapStateToProps)(Plans);
export { connectedPlans as Plans };
If I use a Higher-Order Component (HOC) as a decorator, i.e.,
#withStyles({})
class Bar extends React.Component { ... }
I'd get this error with enzyme:
console.error node_modules/prop-types/checkPropTypes.js:19
Warning: Failed prop type: The prop `classes` is marked as required in `_class`, but its value is `undefined`.
in _class
If I use the function form, i.e.,
const Bar = withStyles({})(class extends React.Component { ... });
there are no errors.
Why?
Note that this warning only happens on a child component; see the code from reproduction steps for what I mean.
Reproduction steps
package.json:
{
"name": "test",
"version": "1.0.0",
"description": "",
"scripts": {
"test": "jest"
},
"author": "",
"dependencies": {
"prop-types": "^15.6.2",
"react": "^16.4.1",
"react-dom": "^16.4.1"
},
"devDependencies": {
"babel-jest": "^23.2.0",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-plugin-transform-decorators-legacy": "^1.3.5",
"babel-preset-env": "^1.7.0",
"babel-preset-react": "^6.24.1",
"enzyme": "^3.3.0",
"enzyme-adapter-react-16": "^1.1.1",
"jest": "^23.3.0"
},
"babel": {
"plugins": [
"transform-class-properties",
"transform-decorators-legacy"
],
"presets": [
"env",
"react"
]
}
}
__tests__/app.test.js:
import Adapter from 'enzyme-adapter-react-16';
import Enzyme from 'enzyme';
import PropTypes from 'prop-types';
import React from 'react';
import { shallow } from 'enzyme';
Enzyme.configure({ adapter: new Adapter() });
const withStyles = styles => Component => class extends React.Component {
render() {
return <Component classes={styles} />
}
}
// This will produce a failed prop type warning:
#withStyles({})
class Bar extends React.Component {
static propTypes = {
classes: PropTypes.object.isRequired,
}
render() {
return <div>test</div>;
}
}
// This will NOT produce a failed prop type warning:
// const Bar = withStyles({})(class extends React.Component {
// static propTypes = {
// classes: PropTypes.object.isRequired,
// }
// render() {
// return <div>test</div>;
// }
// });
class Test extends React.Component {
render() {
return <Bar />;
}
}
it('renders without crashing', () => {
shallow(<Test />);
expect(true).toBe(true);
});
Run npm t
There are two code blocks: one with decoration and the other (currently commented out) with function form. Simply comment out the decorator block and uncomment the function form block to test both cases.
This problem originally arose when using material-ui and I can confirm that both cases render the same UI visually. This prevented me from using the decorator form of withStyles.
Note that there are some more investigations by me here: https://github.com/airbnb/enzyme/issues/1505
The #babel/plugin-proposal-decorators needs come before #babel/plugin-proposal-class-properties, i.e., in the package.json:
"babel": {
"plugins": [
"transform-decorators-legacy",
"transform-class-properties"
],
Hi i am newbie to Reactjs. i am using fineuploader to upload files to the server.i want to create a FineUploader Component ,so that i can use it where ever i want.
package.json
{
"name": "Sample",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"babel-core": "^6.2.1",
"babel-loader": "^6.2.0",
"babel-preset-es2015": "^6.1.18",
"babel-preset-react": "^6.1.18",
"fine-uploader": "^5.7.1",
"react": "^0.14.6",
"react-dom": "^0.14.6",
"webpack": "^1.12.9",
"webpack-dev-server": "^1.14.0"
}
}
webpack.config.js
var path = require("path");
module.exports = {
entry: [
'./Components/Main.js'
],
output:{
path:__dirname,
filename:'bundle.js'
},
resolve: {
alias: {
'fine-uploader': path.resolve('node_modules/fine-uploader/fine-uploader')
}
},
module:{
loaders: [
{
test: /fine-uploader\.js/,
loader: 'exports?qq'
}
],
loaders:[{
test: /\.jsx?$/,
exclude:/node_modules/,
loader:'babel',
query:{
presets: ['react']
}
}]
}
};
FineUploader.js
import React from 'react';
import qq from 'fine-uploader/fine-uploader';
class FineUploader extends React.Component {
constructor (props) {
super(props)
}
componentDidMount () {
const fu = new qq.FineUploaderBasic({
button: this.refs.fu
})
}
render () {
return <div ref='fu'>Upload!</div>
}
}
export default FineUploader;
Main.js
import React from 'react';
import ReactDOM from 'react-dom';
import FineUploader from './FineUploader.js';
var MainContent = React.createClass({
render:function(){
return (
<div>
<FineUploader />
</div>
);
}
});
ReactDOM.render(<MainContent />,document.getElementById('container'));
When i run the Application i am getting the below error
uncaught TypeError: _fineUploader2.default.FineUploaderBasic is not a constructor
i dint no what i am doing wrong ,Plz somebody guide me
To use Fine Uploader with React you will need to create a new uploader instance within the componentDidMount lifecycle method.
Invoked once, only on the client (not on the server), immediately after the initial rendering occurs. At this point in the lifecycle, you can access any refs to your children (e.g., to access the underlying DOM representation).
Fine Uploader needs an actual rendered DOM element for it to attach event handlers, render other DOM elements as children, etc.
Inside of componentDidMount we not only know our component has been created, but we also have a DOM element and we can reference it as such using a ref.
Here's a tiny example component:
class FineUploader extends React.Component {
componentDidMount () {
const fu = new qq.s3.FineUploaderBasic({
button: this.refs.fu
})
}
render () {
return <div ref='fu'>Upload!</div>
}
}
Even though my answer is not completely relevant to the asked question but I would recommend the react-fine-uploader library to make your life easier.
https://github.com/FineUploader/react-fine-uploader