WithStyles not working in Material UI for React - reactjs

I have an app using Material UI Beta where I try to style a simple component as follows:
import { MuiThemeProvider } from 'material-ui/styles';
const styles = theme => ({
container: {
display: 'flex',
flexWrap: 'wrap',
},
textField: {
marginLeft: 200,
marginRight: theme.spacing.unit,
width: 200,
},
menu: {
width: 200,
},
});
export const CreateJob = (props) => {
const { classes } = props;
let confirmDelete = () => {
const r = window.confirm("Confirm deletion of job");
return r === true;
};
return (
<MuiThemeProvider>
<div>
<form onSubmit={props.isEditting ? props.handleEdit : props.handleSubmit} noValidate autoComplete="off">
<h2>Update job details</h2>
<TextField
error={props.jobIdError !== ''}
helperText={props.jobIdError || "Example: ES10"}
autoFocus
margin="dense"
id="jobId"
label="Job ID"
name="jobid"
fullWidth
onChange={props.handleInputChange('jobId')}
value={props.jobId} />
</form>
</div>
</MultiThemeProvider>
I then use this in my parent component as follows:
<CreateJob open={this.state.open} />
However, this yields the following error:
TypeError: Cannot read property 'classes' of undefined

this.state is not defined in your code. In the example, state is defined as
state = {
name: 'Cat in the Hat',
age: '',
multiline: 'Controlled',
currency: 'EUR',
};

Sorry I'm kinda late with an answer, but I just found this question while searching for another solution.
I'm going to assume you also imported withStyles.
Firstly, you don't need to export both the simple component and the enhanced one:
export const CreateJob = props => {...} // lose the 'export'
export default withStyles(styles)(CreateJob); // only export here
Secondly, a real problem: <MuiThemeProvider> should be placed around your highest component(usually the <App> component that you render in your entry point file), so you can customize the default theme to your liking for the whole app; see their example here. I'm not sure, but this might even solve your problem, since that should have thrown another error like in this issue.
I just hope this helps someone, but I cannot be sure about what your exact problem is without the complete component file.

Related

React Beginner - Trouble understanding useContext for dark mode

I'm completing an online program to learn ReactJS. After going over useState we are now learning useContext. Below I'll go over my current understanding of how useContext works, and where I'm facing trouble.
The goal is a simple page with a light/dark mode switch
What I currently understand as the "steps" to using useContext:
Import and initialize createContext
Wrap child components with Provider
Import useContext hook from React so we can use the Context in child components
Access the user Context in desired component(s)
But I'm facing an issue with understanding the code block below
This is the solution to a file named ThemeContext.js.
import { createContext, useContext, useState } from "react";
const ThemeContext = createContext(undefined);
export const ThemeProvider = ({ children }) => {
const [theme, setTheme] = useState("light");
return (
<ThemeContext.Provider
value={{
theme,
toggleTheme: () => setTheme(theme === "light" ? "dark" : "light"),
}}
>
{children}
</ThemeContext.Provider>
);
};
export const useTheme = () => useContext(ThemeContext);
This is the solution to App.js.
import "./App.css";
import { ThemeProvider, useTheme } from "./ThemeContext";
import Switch from "./Switch";
const Title = ({ children }) => {
const { theme } = useTheme();
return (
<h2
style={{
color: theme === "light" ? "black" : "white",
}}
>
{children}
</h2>
);
};
const Paragraph = ({ children }) => {
const { theme } = useTheme();
return (
<p
style={{
color: theme === "light" ? "black" : "white",
}}
>
{children}
</p>
);
};
const Content = () => {
return (
<div>
<Paragraph>
We are a pizza loving family. And for years, I searched and searched and
searched for the perfect pizza dough recipe. I tried dozens, or more.
And while some were good, none of them were that recipe that would
make me stop trying all of the others.
</Paragraph>
</div>
);
};
const Header = () => {
return (
<header>
<Title>Little Lemon 🍕</Title>
<Switch />
</header>
);
};
const Page = () => {
return (
<div className="Page">
<Title>When it comes to dough</Title>
<Content />
</div>
);
};
function App() {
const { theme } = useTheme();
return (
<div
className="App"
style={{
backgroundColor: theme === "light" ? "white" : "black",
}}
>
<Header />
<Page />
</div>
);
}
function Root() {
return (
<ThemeProvider>
<App />
</ThemeProvider>
);
}
export default Root;
Finally, this is the solution to index.js
import "./Styles.css";
import { useTheme } from "../ThemeContext";
const Switch = () => {
const { theme, toggleTheme } = useTheme();
return (
<label className="switch">
<input
type="checkbox"
checked={theme === "light"}
onChange={toggleTheme}
/>
<span className="slider round" />
</label>
);
};
export default Switch;
My questions begin here
Instead of directly wrapping children with Provider, they instead create ThemeProvider that then returns ThemeContext.Provider. Why is this? and why is { children } necessary as seen in App.js along with the return ThemeContext return statement?
This exercise goes beyond what I believe was taught in the lesson, so I could have some holes to fill in my knowledge as far as using { children } along with the use of ThemeProvider. Normally it's demonstrated as <ThemeContext.Provider> wrapping children on the inside. In App it looks like they don't do this, but it's done in the Root, and maybe since they're wrapping App that's why { children } is indicated? I'm not certain about this and I'd just like to know why things were done specifically like this (again, this is unlike what was demonstrated in past exercises). First post, thanks in advance.
EDIT: After looking more into this issue I'm starting to come around and understand how they came up with this solution. One of the few things they didn't do previously that was used in this example was the use of ({ children }). This caused confusion for me at first, but I've come closer to understanding its usage. For example, its use in the Paragraph component:
const Paragraph = ({ children }) => {
const { theme } = useTheme();
return (
<p
style={{
color: theme === "light" ? "black" : "white",
}}
>
{children}
</p>
);
};
Which is later referenced in the Content component as such:
<Paragraph>
We are a pizza loving family. And for years, I searched and searched and
searched for the perfect pizza dough recipe. I tried dozens, or more.
And while some were good, none of them were that recipe that would
make me stop trying all of the others.
</Paragraph>
This simply means to take the children of the Paragraph component and return the information styled as such. Whatever comes inside of Paragraph, in this case a block of text, was returned with the intended style. I thought of deleting this post but maybe it will help someone else. Not sure if adding more about what I learned here would be excessive, and I'm still wrapping my head around the rest of the issue so documenting here isn't my top priority as of now.
React Context is a relatively new feature that the React team introduced to enable an alternative to holding state in a component and prop drilling. The context provider is a node that holds a value, which can be accessed by any node rendered under it (any children or children of children) via the createContext() with useContext or Context.Consumer. When the value of the Provider changes, any component subscribed with useContext or rendered by Consumer will be rerendered.
There is no practical difference between using the provider directly in index.js. What matters is who is rendered under the provider. Keep in mind that JSX's <ThemeProvider> is in reality a call to React.createElement with App in the children argument.
Why create a ThemeProvider? It packages the provider with state. The alternative would be to use the provider directly in Root and create useState there, but it is inflexible and not reusable.
const ThemeContext = createContext(undefined);
function Root() {
const [theme, setTheme] = useState("light");
return (
<ThemeContext.Provider
value={{
theme,
toggleTheme: () => setTheme(theme === "light" ? "dark" : "light"),
}}
>
<App />
</ThemeContext.Provider>
);
}
Note that App is still the children of the provider.

How to create a horizontal timeline in React

There are two questions already on Stackoverflow:
Create Horizontal Timeline With
React How to create responsive horizontal timeline
None of them have any accepted answer. And also my question is specifically related to react-horizontal-timeline.
I'm creating my personal portfolio and I wish to show my education/college journey.
The author has given the code:
const VALUES = [ /* The date strings go here */ ];
export default class App extends React.Component {
state = { value: 0, previous: 0 };
render() {
return (
<div>
{/* Bounding box for the Timeline */}
<div style={{ width: '60%', height: '100px', margin: '0 auto' }}>
<HorizontalTimeline
index={this.state.value}
indexClick={(index) => {
this.setState({ value: index, previous: this.state.value });
}}
values={ VALUES } />
</div>
<div className='text-center'>
{/* any arbitrary component can go here */}
{this.state.value}
</div>
</div>
);
}
}
Since I'm coming from Angular and MVC frameworks, I didn't understand what this HorizontalTimeline is doing there. Is there anything I need to import? I'm asking this because the code is giving this error:
Line 13:22: 'HorizontalTimeline' is not defined react/jsx-no-undef
Looks like the compiler is not able to recognize HorizontalTimeline.
And also I would like to have it as a separate component for example <MyTimeline> or so. Why would I clutter my App.js. Hope I was able to explain. Please pitch in.
You need to import the component.
Unfortunately the vendor's documentation doesn't include the import statement. Further unfortunately still, the vendor's demo imports it directly from their source code. Which is fine if you're using their source code, but useless if you're installing their npm package.
Unless the IDE can find the import for you (VS Code should be able to, but anything could be preventing that) then best guesses would be:
import HorizontalTimeline from 'react-horizontal-timeline';
or:
import { HorizontalTimeline } from 'react-horizontal-timeline';
Check out this timeline component if you are interested. I think it's better for your need and also has much more clear documentation and a better horizontal mode.
react-chrono
Here is an example of a responsive timeline using the react-chrono component. I have also added some code that will automatically change to the vertical mode which is better for mobile view.
import React from "react";
import { Chrono } from "react-chrono";
class EducationTimeline extends React.Component {
constructor(props) {
super(props);
this.state = { matches: window.matchMedia("(min-width: 768px)").matches };
}
componentDidMount() {
const handler = (e) => this.setState({ matches: e.matches });
window.matchMedia("(min-width: 768px)").addEventListener("change", handler);
}
render() {
const items = [
{
title: "example",
cardTitle: "example",
cardSubtitle: "example",
cardDetailedText: "example",
}
];
return (
<div style={{ width: "500px", height: "400px" }}>
<Chrono
items={items}
mode={this.state.matches ? "HORIZONTAL" : "VERTICAL"}
slideShow={false}
itemWidth={"250"}
hideControls={true}
cardHeight={100}
borderLessCards={true}
theme={{
primary: "#01bf71",
secondary: "#010606",
cardBgColor: "#f7f8fa",
cardForeColor: "#010606",
titleColor: "#fff",
}}
></Chrono>
</div>
);
}
}
export default EducationTimeline;

React Select Example not displaying dropdown

I am just trying a React Select Dropdown Example using the below code:
import React from 'react';
import Select from 'react-select';
import '../../../node_modules/bootstrap/dist/css/bootstrap.min.css';
const techCompanies = [
{ label: "Apple", value: 1 },
{ label: "Facebook", value: 2 },
{ label: "Netflix", value: 3 },
{ label: "Tesla", value: 4 },
{ label: "Amazon", value: 5 },
{ label: "Alphabet", value: 6 },
]
const App = () => {
return (
<div className="container">
<div className="row">
<div className="col-md-4" />
<div className="col-md-4">
<Select options={ techCompanies } />
</div>
<div className="col-md-4" />
</div>
</div>
)
};
export default App
Before this , I installed react select
npm i react-select
also installed bootstrap
npm install bootstrap --save
But after running I am getting the error:
Unable to resolve "../../../node_modules/bootstrap/dist/css/bootstrap.min.css" from "components/university/App.js"
Failed building JavaScript bundle.
I can see the bootstrap.min.css under node_modules folder.
If I comment the import I am get the following :
View config not found for name div. Make sure to start component names with a capital letter.
Can anyone tell where am I going wrong?Thanks in Advance.
You can't use html components or the usual web css in react-native. In contrast to react web, react-native will map your components to native android, ios or windows ui components. Therefore your components must be composited of react-native components. I think you should check out this answer which explains the difference between react and react-native in more depth.
In your case you could start with an App Component similiar to this:
import React, { useState } from "react";
import { View, Picker, StyleSheet } from "react-native";
const techCompanies = [
{ label: "Apple", value: 1 },
{ label: "Facebook", value: 2 },
{ label: "Netflix", value: 3 },
{ label: "Tesla", value: 4 },
{ label: "Amazon", value: 5 },
{ label: "Alphabet", value: 6 },
]
const App = () => {
const [selectedValue, setSelectedValue] = useState(1);
return (
<View style={styles.container}>
<Picker
selectedValue={selectedValue}
style={{ height: 50, width: 150 }}
onValueChange={itemValue => setSelectedValue(itemValue)}
>
{techCompanies.map(({ label, value }) =>
<Picker.Item label={label} value={value} key={value} />)}
</Picker>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 40,
alignItems: "center"
}
});
export default App;
see https://reactnative.dev/docs/picker for reference.
Old answer, before we learned that this is about react-native:
Your original code actually looked fine and should work.
However the css import should usually be your first import, because you want styles inside imported components to take precedence over the default styles. source
The added braces and return are not needed at all...
Also I would recommend using
import 'bootstrap/dist/css/bootstrap.min.css'
instead of
import '../../../node_modules/bootstrap/dist/css/bootstrap.min.css'. The Babel+Webpack setup of create-react-app will take care of figuring out the location of the bootstrap module. If you use a relative path instead, there will be errors as soon as you move the file with the import...
Maybe something went wrong during your package installation? I'd suggest that you just try this:
rm -rf ./node_modules
npm install
npm run start
You can verify that your code was working in this sandbox: https://codesandbox.io/s/react-select-bootstrap-sample-g2264?file=/src/App.js
Your import looks fine. Sometimes the error messages throw us off track, as the real error is caused by some other compiling issue. So, try fixing this first:
You are confusing parentheses and curly braces. Plus, you are missing a return. Should be:
const App = () => {
return (
<div className="container">
<div className="row">
<div className="col-md-4" />
<div className="col-md-4">
<Select options={ techCompanies } />
</div>
<div className="col-md-4" />
</div>
</div>
);
};

Make onClick on <li> go to another view

i'm new on react and i'm doing a project, actually it's a to do list, and i need to make a router that when i click on my item on they send me to details of this item. Here's my actual code. That's my app.js
import React, { Component } from 'react';
import List from './List';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
term: '',
items: []
};
}
onChange = (event) => {
this.setState({ term: event.target.value });
}
onSubmit = (event) => {
event.preventDefault();
this.setState({
term: '',
items: [...this.state.items, this.state.term]
});
}
render() {
return (
<div style={{display: "flex", flexDirection: 'column', alignItems: "center", margin: 5}}>
<form onSubmit={this.onSubmit}>
<input style={{borderRadius: 3, borderColor: "black"}}
value={this.state.term} onChange={this.onChange} />
<button style={{borderRadius: 3, borderColor: "black"}}>
Adicionar</button>
</form>
<List items={this.state.items}/>
</div>
);
}
}
And here my List.js
import React from 'react';
const List = ({ items }) => (
<ul style={{display: "block", listStyleType: "none", backgroundColor: "red"}}>
{
items && items.map((item, index) => <li key={index}>{item}</li>)
}
</ul>
);
export default List;
So i now i will have to use some library to make the route, but first i need to know how i make my itens clickable and when i click they return something that can i redirect to a detail view. Make sense?
And there's a library that you guys recommend to do this job?
Thank you
As i think, you need to use custom links in react As:
1) npm i react-router-dom
2) import {Link} from 'react-router-dom';
3) And finally use <Link to="paste_your_url_here" />
you can also place <Link to='' /> inside of ul, li.
You could add a onClick on each li that redirects to the url you want (implementation may vary based off the lib you choose to handle rooting), but that's not really a good idea since in HTML li are not supposed to be clickable.
What I would do is have a link (again, see with the routing lib - generally it provides a <Link /> component) inside each <li>. This provides better semantic to your code.
Hope this makes sense.
As for a good library... React-router or reach-router are pretty nice!

ReactJS Invalid hook call while add useStyle variable

I am trying to write a from but it throws me this 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:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
This is App.js file where i am writing the form:
import React, { Component } from 'react';
import TextField from '#material-ui/core/TextField';
import './App.css';
import useStyles from '../src/styleMaker'
import { makeStyles } from '#material-ui/core/styles';
class App extends Component {
state = {
ssn: '',
}
useStyles = makeStyles(theme => ({
container: {
display: 'flex',
flexWrap: 'wrap',
},
textField: {
marginLeft: theme.spacing(1),
marginRight: theme.spacing(1),
width: 200,
},
dense: {
marginTop: 19,
},
menu: {
width: 200,
},
paper: {
padding: theme.spacing(2),
textAlign: 'center',
color: theme.palette.text.secondary,
},
button: {
margin: theme.spacing(1),
},
}));
classes = useStyles();
onHandleChange(event) {
this.setState({
[event.target.name]: event.target.value
});
}
render() {
return (
<React.Fragment>
<form noValidate autoComplete="off">
<TextField
id=""
label="SSN"
value={this.state.ssn}
onChange={(event) => this.onHandleChange(event)}
type="number"
name='ssn'
margin="normal"
className={this.classes.textField}
/>
<TextField
id=""
label="SSN"
value={this.state.phone}
onChange={(event) => this.onHandleChange(event)}
type="number"
name='phone'
margin="normal"
className={this.classes.textField}
/>
</form>
</React.Fragment>
);
}
}
export default App;
Can anyone help me whats wrong with my code? Why my code is not working?
When i add userStyle, then i throws me the error, Can anyone help me in this case?
I spend hour to fix this issue but now i just give up on it. Anyone helps will make my day.. Thanks in advance
As the error is suggesting you
Hooks can only be called inside of the body of a function component
You are using a class based component here, you can convert this class based component to functional component, you would also need to use useState Hook for your state in functional Component, you can do this,
const App = () => {
const [ssn, setSsn ] = useState('')
const classes = useStyles()
// remaining code
return (
....
)
}
Also when you use functional component you cannot use this inside functional component
Hope it helps
You can not use hooks from within class based components. If you want to use hooks, you need to convert your components to functional, something along the following lines:
function App() {
const classes = useStyles();
...
return (
...
)
}

Resources