<FormControl /> does not accept variant Prop - javascript

I wonder why <FormControl /> does not accept the prop variant. According to the docs, this prop is available.
import React from "react";
import { render } from "react-dom";
import FormControl from "#material-ui/core/FormControl";
import Select from "#material-ui/core/Select";
import MenuItem from "#material-ui/core/MenuItem";
const App = () => {
return (
<div>
<FormControl variant="outlined">
<Select value="foo" onChange={() => {}} autoWidth={true}>
<MenuItem value="foo">Kitten</MenuItem>
<MenuItem value="bar">Puppy</MenuItem>
</Select>
</FormControl>
</div>
);
};
render(<App />, document.getElementById("root"));
However, it does not work. Here is a Sandbox reproducing the problem.
https://codesandbox.io/s/material-ui-9ut2q

import React, { useState } from "react";
import { render } from "react-dom";
import FormControl from "#material-ui/core/FormControl";
import Select from "#material-ui/core/Select";
import MenuItem from "#material-ui/core/MenuItem";
const App = () => {
const [state, setValues] = useState({
defaults: "foo"
});
const changeValue = e => {
setValues({ ...state, defaults: e.target.value });
};
return (
<div>
<FormControl variant="outlined">
<Select
value={state.defaults}
onChange={e => {
changeValue(e);
}}
autoWidth={true}
>
<MenuItem value="foo">Kitten</MenuItem>
<MenuItem value="bar">Puppy</MenuItem>
</Select>
</FormControl>
</div>
);
};
render(<App />, document.getElementById("root"));
package.json
{
"dependencies": {
"react": "^16.7.0-alpha.2",
"react-dom": "^16.7.0-alpha.2",
...
},
https://codesandbox.io/s/material-ui-ksggx?fontsize=14
try this it will work

Related

How to run material UI example snippets within a component

All I want to achieve is a page that has a header that reads: "Survey Start" and then a user select interface under that. I am envisioning a very simple component:
export class Survey extends Component {
state = {
}
render() {
return (
<React.Fragment>
<h2>Survey Start</h2>
<Survey sorcery here>
</React.Fragment>
)
}
Then my App.js runs this.
I aim to replace "survey sorcery" with the "some important helper text" version of MaterialUI's user select. I directly copied from the javascript source that was provided. Seen here:
https://material-ui.com/components/selects/
I thought it would be as simple as copying and pasting within my component:
import React, { Component } from 'react';
import { makeStyles } from '#material-ui/core/styles';
import InputLabel from '#material-ui/core/InputLabel';
import MenuItem from '#material-ui/core/MenuItem';
import FormHelperText from '#material-ui/core/FormHelperText';
import FormControl from '#material-ui/core/FormControl';
import Select from '#material-ui/core/Select';
export class Survey extends Component {
state = {
}
const useStyles = makeStyles((theme) => ({
formControl: {
margin: theme.spacing(1),
minWidth: 120,
},
selectEmpty: {
marginTop: theme.spacing(2),
},
}));
export default function SimpleSelect() {
const classes = useStyles();
const [age, setAge] = React.useState('');
const handleChange = (event) => {
setAge(event.target.value);
};
}
render() {
return (
<React.Fragment>
<h2>Survey Start</h2>
<FormControl className={classes.formControl}>
<InputLabel id="demo-simple-select-helper-label">Age</InputLabel>
<Select
labelId="demo-simple-select-helper-label"
id="demo-simple-select-helper"
value={age}
onChange={handleChange}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
<FormHelperText>Some important helper text</FormHelperText>
</FormControl>
</React.Fragment>
);
}
}
However this returned several errors, including citing the line where I defined useStyles:
The 'const' modifier can only be used in Type Script files.
Not sure why it threw that since I was careful to click the javascript example file on the example source code.
Question
How do I get the materialUI example user select to integrate with a vanilla component?
You are mixing components inside components.
Try to see thinking in react to get a better understanding of how component works. You need to export <SimpleSelect /> as its own component, then use it in your <Survey /> component.
Refactored code:
import React, { Component } from 'react';
import { makeStyles } from '#material-ui/core/styles';
import InputLabel from '#material-ui/core/InputLabel';
import MenuItem from '#material-ui/core/MenuItem';
import FormHelperText from '#material-ui/core/FormHelperText';
import FormControl from '#material-ui/core/FormControl';
import Select from '#material-ui/core/Select';
const useStyles = makeStyles(theme => ({
formControl: {
margin: theme.spacing(1),
minWidth: 120
},
selectEmpty: {
marginTop: theme.spacing(2)
}
}));
function SimpleSelect() {
const classes = useStyles();
const [age, setAge] = React.useState('');
const handleChange = event => {
setAge(event.target.value);
};
return (
<FormControl className={classes.formControl}>
<InputLabel id="demo-simple-select-helper-label">Age</InputLabel>
<Select
labelId="demo-simple-select-helper-label"
id="demo-simple-select-helper"
value={age}
onChange={handleChange}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
<FormHelperText>Some important helper text</FormHelperText>
</FormControl>
);
}
export class Survey extends Component {
state = {};
render() {
return (
<>
<h2>Survey Start</h2>
<SimpleSelect />
</>
);
}
}

Material-UI ListItem as Link Component Changes URL but Not Rendering Component

This is my first time asking a question here, but I am truly stumped.
I'm coding a navbar for my school project website. I'm using Material-UI's List component within the Appbar component. There are two issues I'm seeing: 1) the initial onClick will cause the route to path to '/' and 2) the second onClick will change to the proper route, but not render the desired component. Please see a gif of the issue at the bottom if it helps.
I have been working at this for a few days now, and I am not sure what I am missing 😔
Here is my code for the List component:
PageList.jsx
import React from "react";
import clsx from "clsx";
import { makeStyles } from "#material-ui/core/styles";
import useMediaQuery from "#material-ui/core/useMediaQuery";
import { List, ListItem, ListItemText, ListItemIcon } from "#material-ui/core";
import { PAGES, usePageStatus } from "constants/pages";
const PageItem = ({ page }) => {
const classes = useStyles();
const { label, route, icon } = usePageStatus(page);
return (
<ListItem button component={Link} to={route}>
<ListItemIcon className={classes.icon}>{icon}</ListItemIcon>
<ListItemText primary={label} />
</ListItem>
);
};
const PageList = () => {
const classes = useStyles();
const isMobile = useMediaQuery("(max-width: 600px)", {
noSsr: true,
});
return (
<List className={clsx(isMobile ? classes.mobileList : classes.list)}>
{PAGES.map((page) => (
<PageItem page={page} key={page} />
))}
</List>
);
};
export default PageList;
Here is my code for where I use the PageList component: TopNav.jsx
import React, { useState } from "react";
import clsx from "clsx";
import { makeStyles } from "#material-ui/core/styles";
import useMediaQuery from "#material-ui/core/useMediaQuery";
import {
AppBar,
Toolbar,
Typography,
IconButton,
Drawer,
} from "#material-ui/core";
import MenuIcon from "#material-ui/icons/Menu";
import ChevronRightIcon from "#material-ui/icons/ChevronRight";
import PageList from "./PageList";
import MobileTopMenu from './MobileTopMenu'
const TopNav = () => {
const classes = useStyles();
const isMobile = useMediaQuery("(max-width: 600px)", {
noSsr: true,
});
return (
<AppBar position="static" elevation={0} className={classes.appBar}>
<Toolbar>
<Typography component="a" href="/" className={classes.title}>
Amber+
</Typography>
{isMobile ? <MobileTopMenu /> : <PageList />}
</Toolbar>
</AppBar>
);
};
Here is where I placed my nav bar and my routing code: routes.js
import React from "react";
import { Route, Router, Redirect, Switch } from "react-router-dom";
import { createBrowserHistory } from "history";
import { Home, Missing, Found, Search } from "pages";
import { PAGE_ROUTES, HOME, MISSING, FOUND, SEARCH } from "constants/pages";
import TopNav from "components/common/Nav/TopNav";
const history = createBrowserHistory();
const Routes = () => {
return (
<Router history={history}>
<TopNav />
<Switch>
<Route exact path={PAGE_ROUTES[HOME]} component={Home} />
<Route exact path={PAGE_ROUTES[MISSING]} component={Missing} />
<Route exact path={PAGE_ROUTES[FOUND]} component={Found} />
<Route exact path={PAGE_ROUTES[SEARCH]} component={Search} />
<Route path="*">
<Redirect to={PAGE_ROUTES[HOME]} component={Home} />
</Route>
</Switch>
</Router>
);
};
And this is my code for my page constants: pages.js
export const HOME = "Home";
export const MISSING = "Missing";
export const FOUND = "Found";
export const SEARCH = "Search";
export const PAGES = [HOME, MISSING, FOUND, SEARCH];
export const PAGE_ROUTES = {
[HOME]: "/",
[MISSING]: "/missing",
[FOUND]: "/found",
[SEARCH]: "/search",
};
export const PAGE_ICONS = {
[HOME]: <HomeOutlinedIcon fontSize="small" />,
[MISSING]: <FavoriteBorderIcon fontSize="small" />,
[FOUND]: <ErrorOutlineIcon fontSize="small" />,
[SEARCH]: <SearchIcon fontSize="small" />,
};
export const usePageStatus = (page) => {
const route = PAGE_ROUTES[page];
const icon = PAGE_ICONS[page];
const label = page;
return { route, icon, label };
};
Here is a gif of what I am seeing:
Try this on PageList.jsx
import React, {useCallback} from "react";
import clsx from "clsx";
import { makeStyles } from "#material-ui/core/styles";
import useMediaQuery from "#material-ui/core/useMediaQuery";
import { List, ListItem, ListItemText, ListItemIcon } from "#material-ui/core";
import { PAGES, usePageStatus } from "constants/pages";
import { useHistory } from "react-router-dom";
const PageItem = ({ page }) => {
const classes = useStyles();
const { label, route, icon } = usePageStatus(page);
const history = useHistory();
const goto = useCallback((path) => history.push(path), [history]);
return (
<ListItem button onClick={() => goto(route)}>
<ListItemIcon className={classes.icon}>{icon}</ListItemIcon>
<ListItemText primary={label} />
</ListItem>
);
};
const PageList = () => {
const classes = useStyles();
const isMobile = useMediaQuery("(max-width: 600px)", {
noSsr: true,
});
return (
<List className={clsx(isMobile ? classes.mobileList : classes.list)}>
{PAGES.map((page) => (
<PageItem page={page} key={page} />
))}
</List>
);

How to use material-ui TextField with react-phone-number-input

I'd like to supply a material UI TextField component to the PhoneInput component from react-phone-number-input as the inputComponent prop.
However, I don't seem to be able to successfully apply the ref. Although I see the Material UI TextField component rendered to the UI and state is successfully updated with the value, it keeps loosing focus after the first value has been typed.
import React, { forwardRef, createRef } from 'react';
import { TextField } from '#material-ui/core';
import 'react-phone-number-input/style.css';
import PhoneInput from 'react-phone-number-input';
const SampleComponent = ({ handleChange }) => {
const phoneInput = forwardRef((props, ref) => {
return (
<TextField
inputRef={ref}
fullWidth
label="Phone Number"
variant="outlined"
name="phone"
onChange={handleChange}
/>
);
});
const ref = createRef();
return (
<PhoneInput ref={ref} inputComponent={phoneInput} />
);
};
So I was able to get it to work using the following method. Any suggestions on how to improve this are more than welcome.
I have a separate file called PhoneNumber.jsx
import { forwardRef } from 'react'
import TextField from '#material-ui/core/TextField'
import { makeStyles } from '#material-ui/core/styles'
const useStyles = makeStyles(theme => ({
input: {
backgroundColor: '#fff'
}
}))
const phoneInput = (props, ref) => {
const classes = useStyles()
return (
<TextField
{...props}
InputProps={{
className: classes.input
}}
inputRef={ref}
fullWidth
size='small'
label='Phone Number'
variant='outlined'
name='phone'
/>
)
}
export default forwardRef(phoneInput)
And my form file:
import PhoneInput from 'react-phone-number-input'
import CustomPhoneNumber from '../components/prebuilt/PhoneNumber'
...
<PhoneInput
placeholder='Enter phone number'
value={phone}
onChange={setPhone}
inputComponent={CustomPhoneNumber}
/>
...
There is also a package for Material UI v5 (or MUI) called Mui tel input and it's working with React 17 and 18 !
Simply way to use. Phone validation available too.
Check the doc here : https://github.com/viclafouch/mui-tel-input
import React from 'react'
import { MuiTelInput } from 'mui-tel-input'
const MyComponent = () => {
const [value, setValue] = React.useState('')
const handleChange = (newValue) => {
setValue(newValue)
}
return <MuiTelInput label="Phone" fullWidth value={value} onChange={handleChange} />
}

How to get categories in wordpress rest api using react-redux

I am trying to get categories name in reactjs from wordpress rest api using redux.
actions/categories.js
import axios from 'axios';
import { GET_CATEGORIES } from './types';
export const getCategories = () => dispatch => {
axios.get('/wp-json/wp/v2/categories')
.then(res => {
console.log(res);
dispatch({
type: GET_CATEGORIES,
payload: res.data
});
}).catch(err => console.log(err));
}
reducers/categories.js
import {GET_CATEGORIES} from '../actions/types';
const initialState = {
categories: []
}
export default function (state = initialState, action) {
switch (action.type) {
case GET_CATEGORIES:
return {
...state,
categories: action.payload
}
default:
return state;
}
}
reducers/index.js
import {combineReducers} from 'redux';
import posts from './posts';
import categories from './categories';
export default combineReducers({
posts,
categories
});
I tried this same way to get the post and it worked . But in case of categories it gives nothing. I even try to console.log(res) in action/categories.js but gives no response in browser. anyone please explain it to me why this is happening.
this is here i am trying to render this sideDrawer.js
import React from 'react'
import Drawer from '#material-ui/core/Drawer';
import List from '#material-ui/core/List';
import Divider from '#material-ui/core/Divider';
import IconButton from '#material-ui/core/IconButton';
import ChevronLeftIcon from '#material-ui/icons/ChevronLeft';
import ChevronRightIcon from '#material-ui/icons/ChevronRight';
import ListItem from '#material-ui/core/ListItem';
import ListItemIcon from '#material-ui/core/ListItemIcon';
import ListItemText from '#material-ui/core/ListItemText';
import InboxIcon from '#material-ui/icons/MoveToInbox';
import MailIcon from '#material-ui/icons/Mail';
import { connect } from 'react-redux';
import {getCategories} from '../actions/categories';
function SideDrawer({ handleDrawerClose, open, classes, theme}) {
return (
<Drawer
className={classes.drawer}
variant="persistent"
anchor="left"
open={open}
classes={{
paper: classes.drawerPaper,
}}
>
<div className={classes.drawerHeader}>
<IconButton onClick={handleDrawerClose}>
{theme.direction === 'ltr' ? <ChevronLeftIcon /> : <ChevronRightIcon />}
</IconButton>
</div>
<Divider />
<List>
{['Inbox', 'Starred', 'Send email', 'Drafts'].map((text, index) => (
<ListItem button key={text}>
<ListItemIcon>{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}</ListItemIcon>
<ListItemText primary={text} />
</ListItem>
))}
</List>
<Divider />
<List>
{['All mail', 'Trash', 'Spam'].map((text, index) => (
<ListItem button key={text}>
<ListItemIcon>{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}</ListItemIcon>
<ListItemText primary={text} />
</ListItem>
))}
</List>
</Drawer>
)
}
const mapStateToProps = state => ({
categories: state.categories.categories
})
export default connect(mapStateToProps, {getCategories})(SideDrawer);

How come react-router-dom does not change URL on click?

I am having trouble changing the URL and getting the component to load when using react-router-dom. If I manually enter the URL the component will load, however, the URL (and component) does not change when I click on the link. In this case, I am trying to load the '/industry/aerospace' page. Thanks!
Here's my code:
App.js:
import React from 'react'
import { compose } from 'redux'
import { Route, Switch, withRouter } from 'react-router-dom'
import { MuiThemeProvider } from '#material-ui/core/styles'
import LandingPage from '../../home'
import AnalyzerProductPage from '../../home/analyzer'
import MonitorProductPage from '../../home/monitor'
import Signout from '../../home/signout'
import Industry from '../../home/industry'
class App extends React.PureComponent {
render() {
return (
<div>
<MuiThemeProvider theme={muiTheme} >
<Switch>
<Route exact path="/" component={LandingPage} />
<Route exact path="/version" component={Version} />
<Route exact path="/signout_success" component={LandingPage} />
<Route exact path="/signout" component={Signout} />
<Route exact path="/liquidtool-analyzer" component={AnalyzerProductPage} />
<Route exact path="/liquidtool-monitor" component={MonitorProductPage} />
<Route exact path="/industry/:industry" component={Industry} />
</Switch>
</MuiThemeProvider>
<NotificationHandler />
<RestCallProgressBar />
</div>
)
}
}
export default compose(
withRouter,
)(App)
HomeHeader.js (with link to page):
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { Link } from 'react-router-dom'
// material-ui
import { withStyles } from '#material-ui/core/styles'
class HomeHeader extends Component {
state = {
value: false,
anchorEl: null
};
handleIndustriesClick = (event) => {
this.setState({ anchorEl: event.currentTarget })
};
handleIndustriesClose = (pageID) => {
this.setState({ anchorEl: null })
}
handleDashboardClick = () => {
this.props.history.push('/dashboard')
};
handleChange = (event, value) => {
this.setState({ value })
};
render() {
const { classes } = this.props
const { value } = this.state
const { anchorEl } = this.state
return (
<AppBar className={classes.appBar} elevation={this.props.elevation}>
<Hidden smDown>
<Grid container justify="space-between" alignItems="center">
<Tabs value={value} onChange={this.handleChange}>
<Tab label="monitor" />
<Tab label="sensor" />
<Tab
label="industries"
aria-owns={anchorEl ? 'industries-menu' : null}
aria-haspopup={true}
onClick={this.handleIndustriesClick}
/>
<Menu
id="industries-menu"
anchorEl={anchorEl}
open={Boolean(anchorEl)}
onClose={this.handleIndustriesClose}
>
<MenuItem onClick={this.handleIndustriesClose}><Link to={'/industry/aerospace'}></Link>Aerospace</MenuItem>
</Menu>
</Tabs>
</Grid>
</Hidden>
</AppBar>
)
}
}
export default withStyles(styles)(HomeHeader)
Industry.js (Component to load):
import React, { Component } from 'react';
import Typography from '#material-ui/core/Typography';
import HomeHeader from '../components/HomeHeader'
class Industry extends Component {
render() {
return(
<div>
<HomeHeader />
<Typography>Hey</Typography>
</div>
)
}
}
export default Industry
try to wrap MenuItem from Link component:
<Link to='/industry/aerospace'>
<MenuItem>
Aerospace
</MenuItem>
</Link>
since you are using material-ui you can also use component prop in MenuItem (which will set the component as root)
<MenuItem component={Link} to='/industry/aerospace'>
Aerospace
</MenuItem>
hope this will help you

Categories

Resources