How to Put Drawer below the Header React-JS - javascript

I'm new in react and I have useStyles in my code for changing the style of the drawer
const useStyles = makeStyles((theme) => ({
drawer: {
marginTop: 56,
}
}));
class PageMenu extends React.Component {
GetMenuItems() {
var classes = useStyle();
<div>
<Drawer
open={this.props.DrawerOpen}
anchor="right"
variant="persistent"
onClose={this.fixthew}
classes = {classes.drawer}
>
---some element------
</Drawer>
<\div>
}
}
render() {
return(
<div>
{GetMenuItems}
</div>
)
}
the problem is ReferenceError: useStyle is not defined and GetMenuItems should be before the render

Use withStyles instead of makeStyles for Class Components.

many mistakes:
You are using the useStyles hook in a class component (hooks are only for functional components)..
You defining the component as one of class methud... u shouldn't do so..
You pass the class in the classes prop instead of in className prop
instead use a functional component like so:
function MenuItems(){
var classes = useStyle();
return <div>
<Drawer
open={this.props.DrawerOpen}
anchor="right"
variant="persistent"
onClose={this.fixthew}
className = {classes.drawer}
>
---some element------
</Drawer>
<\div>
}
function PageMenu(){
return(
<div>
<MenuItems/>
</div>
)
}
if you are a beginner i can advice you to use functional component with hooks and learn the diffrences...
also, Matirial-Ui is a tough Library u better learn the customizations in this library and the ways they offer to style components... (there is many though..)

Related

HOC for JSX element - rendering jsx with wrapped element

I want to call a ReactJS HOC to wrap a tooltip around JSX.
The call should be able like this:
withTooltip(JSX, "very nice")
Therefor I have created this function:
import React from "react";
import MUITooltip from "#material-ui/core/Tooltip";
import useStyles from "./index.styles";
const withTooltip = (Component, text: string) => (props) => {
const classes = useStyles();
return (
<MUITooltip className={classes.root} title={text}>
<Component {...props} />
</MUITooltip>
);
};
export default withTooltip;
The call:
import withTooltip from "commons/withTooltip/withTooltip";
const dialogBtn =
isOk &&
withTooltip(
<div className={classes.buttonWithLoader}>
<OpenDialogButton
variant={BaseButtonVariant.Icon}
openDialogAttributes={areas.button.openDialogAttributes}
/>
</div>,
"Very nice",
);
return (
<Fragment>
{dialogBtn}
</Fragment>
);
It says:
Functions are not valid as a React child. This may happen if you return a Component instead of from render. Or maybe you meant to call this function rather than return it
How to solve it ?
Your HOC accepts a Component argument while you are passing in JSX. Try wrapping the JSX with a function or pass in a component which renders the Button.
However, in your case, you probably want to have control over the toolTip text in your component. If this is the case, I would not use a HOC for this, but rather a wrapping Component.
function WithTooltip({ classes, text, children }) {
return (
<MUITooltip className={classes.root} title={text}>
{children}
</MUITooltip>
);
}
export default WithTooltip;
const dialogBtn = isOk && (
<WithTooltip text="Very nice">
<div className={classes.buttonWithLoader}>
<OpenDialogButton
variant={BaseButtonVariant.Icon}
openDialogAttributes={areas.button.openDialogAttributes}
/>
</div>
</WithTooltip>
);

How to use shouldComponentUpdate with React Hooks?

I've been reading these links:
https://reactjs.org/docs/hooks-faq.html#how-do-i-implement-shouldcomponentupdate
https://reactjs.org/blog/2018/10/23/react-v-16-6.html
In the first link it says (https://reactjs.org/docs/hooks-faq.html#from-classes-to-hooks):
shouldComponentUpdate: See React.memo
The second link also states that:
Class components can bail out from rendering when their input props are the same using PureComponent or shouldComponentUpdate. Now you can do the same with function components by wrapping them in React.memo.
What is desired:
I want Modal to render only when the Modal is visible (managed by this.props.show)
For class component:
shouldComponentUpdate(nextProps, nextState) {
return nextProps.show !== this.props.show;
}
How can I use memo instead in a functional component - here, in Modal.jsx?
The related code:
Functional component Modal.jsx (I don't know how to check for props.show)
import React, { useEffect } from 'react';
import styles from './Modal.module.css';
import BackDrop from '../BackDrop/BackDrop';
const Modal = React.memo(props => {
useEffect(() => console.log('it did update'));
return (
<React.Fragment>
<BackDrop show={props.show} clicked={props.modalClosed} />
<div
className={styles.Modal}
style={{
transform: props.show ? 'translateY(0)' : 'translateY(-100vh)',
opacity: props.show ? '1' : '0'
}}>
{props.children}
</div>
</React.Fragment>
);
});
export default Modal;
The part of class component PizzaMaker jsx that renders Modal:
return (
<React.Fragment>
<Modal show={this.state.purchasing} modalClosed={this.purchaseCancel}>
<OrderSummary
ingredients={this.state.ingredients}
purchaseCancelled={this.purchaseCancel}
purchaseContinued={this.purchaseContinue}
price={this.state.totalPrice}
/>
</Modal>
...
</React.Fragment>
);
Here is the documentation for React.memo
You can pass a function to control the comparison :
const Modal = React.memo(
props => {...},
(prevProps, nextProps) => prevProps.show === nextProps.show
);
when the function returns true, the component will not be re-rendered
Also you can use in export statement like:
export default memo(Modal, (prevProps, nextProps) => prevProps.show === nextProps.show) ;

Unable to pass props between classes using React

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.3/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/0.14.3/react-dom.min.js"></script>
class carSelection extends React.Component {
render(){
return(
<Button> {this.props.name} </Button>
);
}
}
class App extends Component {
constructor(props) {
super(props);
this.state = {
currentPage: 'Your Car',
carSelected: null
};
}
renderCarsList() {
//const carNames = ['porsche', 'Ford', 'Subaru'];
const carName = "Porsche";
return (
//{carNames.map((carName) => <carSelection name = {carName} />)} was inside div
<div>
<carSelection name = {carName} />
</div>
);
}
render() {
const menuItems = [
"Your Car"
];
return (
<Grid centered celled padded>
<Grid.Row>
<Grid.Column width={2}>
{menuItems.map(item => (<Button fluid>{item} </Button>))}
</Grid.Column>
<Grid.Column width={10}>
{this.renderCarsList()}
</Grid.Column>
</Grid.Row>
</Grid>
);
}
}
export default App;
I am trying to pass a prop from renderCarsList() to carSelection. Like this it builds but does not display any buttons. I have been trying to do it the same way as the react tic tac toe tutorial. I also tried with carSelection as a function but no luck.
I have not been able to do anything with this form:<carSelection name = {carName} />. When it was a function it worked using carSlection() but I cannot pass props like that.
Write CarSelection with capital C. Lower-case names are considered to be HTML tags.
You shouldn't use camel-case naming in your class name. Try to use pascal naming instead.
eg: CarSelection
Your carSelection component should capitalize the first letter。React will recognize the component with Capital lowercase to be native html element.

How to use React.forwardRef in a class based component?

I'm trying to use React.forwardRef, but tripping over how to get it to work in a class based component (not HOC).
The docs examples use elements and functional components, even wrapping classes in functions for higher order components.
So, starting with something like this in their ref.js file:
const TextInput = React.forwardRef(
(props, ref) => (<input type="text" placeholder="Hello World" ref={ref} />)
);
and instead defining it as something like this:
class TextInput extends React.Component {
render() {
let { props, ref } = React.forwardRef((props, ref) => ({ props, ref }));
return <input type="text" placeholder="Hello World" ref={ref} />;
}
}
or
class TextInput extends React.Component {
render() {
return (
React.forwardRef((props, ref) => (<input type="text" placeholder="Hello World" ref={ref} />))
);
}
}
only working :/
Also, I know I know, ref's aren't the react way. I'm trying to use a third party canvas library, and would like to add some of their tools in separate components, so I need event listeners, so I need lifecycle methods. It may go a different route later, but I want to try this.
The docs say it's possible!
Ref forwarding is not limited to DOM components. You can forward refs to class component instances, too.
from the note in this section.
But then they go on to use HOCs instead of just classes.
The idea to always use the same prop for the ref can be achieved by proxying class export with a helper.
class ElemComponent extends Component {
render() {
return (
<div ref={this.props.innerRef}>
Div has a ref
</div>
)
}
}
export default React.forwardRef((props, ref) => <ElemComponent
innerRef={ref} {...props}
/>);
So basically, we are forced to have a different prop to forward ref, but it can be done under the hub. It's important that the public use it as a normal ref.
class BeautifulInput extends React.Component {
const { innerRef, ...props } = this.props;
render() (
return (
<div style={{backgroundColor: "blue"}}>
<input ref={innerRef} {...props} />
</div>
)
)
}
const BeautifulInputForwardingRef = React.forwardRef((props, ref) => (
<BeautifulInput {...props} innerRef={ref}/>
));
const App = () => (
<BeautifulInputForwardingRef ref={ref => ref && ref.focus()} />
)
You need to use a different prop name to forward the ref to a class. innerRef is commonly used in many libraries.
Basically, this is just a HOC function. If you wanted to use it with class, you can do this by yourself and use regular props.
class TextInput extends React.Component {
render() {
<input ref={this.props.forwardRef} />
}
}
const ref = React.createRef();
<TextInput forwardRef={ref} />
This pattern is used for example in styled-components and it's called innerRef there.
This can be accomplished with a higher-order component, if you like:
import React, { forwardRef } from 'react'
const withForwardedRef = Comp => {
const handle = (props, ref) =>
<Comp {...props} forwardedRef={ref} />
const name = Comp.displayName || Comp.name
handle.displayName = `withForwardedRef(${name})`
return forwardRef(handle)
}
export default withForwardedRef
And then in your component file:
class Boop extends React.Component {
render() {
const { forwardedRef } = this.props
return (
<div ref={forwardedRef} />
)
}
}
export default withForwardedRef(Boop)
I did the work upfront with tests & published a package for this, react-with-forwarded-ref: https://www.npmjs.com/package/react-with-forwarded-ref
Incase you need to reuse this in many difference components, you can export this ability to something like withForwardingRef
const withForwardingRef = <Props extends {[_: string]: any}>(BaseComponent: React.ReactType<Props>) =>
React.forwardRef((props, ref) => <BaseComponent {...props} forwardedRef={ref} />);
export default withForwardingRef;
usage:
const Comp = ({forwardedRef}) => (
<input ref={forwardedRef} />
)
const EnhanceComponent = withForwardingRef<Props>(Comp); // Now Comp has a prop called forwardedRef
In case anyone is still having trouble combining React.forwardRef() with a HOC like react-redux connect() then this is how I got it to work:
export default connect(mapStateToProps, mapDispatchToProps)(
React.forwardRef((props, ref) => <MyComponent innerRef={ref} {...props} />)
);

How to write a wrapper around a material UI component using React JS?

I am using Material UI next library and currently I am using List component. Since the library is in beta, lot of its parameter names get changed. To solve this I am planning to write a wrapper around the required components so that things wont break. My list component :
<List dense>
<List className={classes.myListStyles}>
<ListItem disableGutters/>
</List>
</List>
How should I write the wrapper for the List(say myListWrapper) and ListItem so that the wrapper component can handle props and pass them to the actual MUI list component inside?
I had worked on MUI wrappers, writing my own library for a project. The implementation we are focusing, is to pass the props to inner/actual-MUI component from the our wrapper component. with manipulation. In case of wrapping props for abstraction.
Following is my approach to the solution:
import { List as MaterialList } from 'material-ui/List';
import { React } from 'react';
import { ListItem as MaterialListI } from 'material-ui/ListItem';
class List extends MaterialList {
constructor(props){
const propsToPass = {
prop1 : change(props.prop1),
...props
}
super(propsToPass);
}
};
class ListItem extends MaterialListItem {
const propsToPass = {
prop1 : change(props.prop1),
prop2 : change(props.prop2),
...props
}
super(propsToPass);
}
};
class App extends React.Component {
render () {
return (
<List prop='value' >
<ListItem prop1={somevalue1} prop2={somevalue2} />
<ListItem prop1={somevalue1} prop2={somevalue2} />
<ListItem prop1={somevalue1} prop2={somevalue2} />
</List>
)
}
};
Above code will allow following things to do with your component:
You can use the props with exact names, as used in Material UI.
You can manipulate/change/transform/reshape you props passed from outside.
If props to you wrapper components are passed with exactly same names as MUI is using, they will directly be sent to the inner component. (... operator.)
You can use Component with exact same name as material is using to avoid confusion.
Code is written according to advance JSX and JavaScript ES6 standards.
You have a space to manipulate your props to pass into the MUI Components.
You can also implement type checking using proptypes.
You can ask for any confusion/query.
You can write it like this:
const MyList = props => (
<List
{/*mention props values here*/}
propA={props.A}
propB={props.B}
>
{props.children}
</List>
)
const MyListItem = props => (
<ListItem
{/*mention props values here*/}
propA={props.A}
propB={props.B}
>
{props.children}
</ListItem>
)
Now you need to use MyList and MyListItem, decide the prop names for these component (as per your convenient), and inside these component map those values to actual Material-UI component properties.
Note:
If you are using the same prop names (same name as material-ui component expect) for your component then you can write like this also:
const MyList = ({children, ...rest}) => <div {...rest}>{children}</div>
const MyListItem = ({children, ...rest}) => <p {...rest}>{children}</p>
Check this example:
const A = props => <div>{props.children}</div>
const B = props => <p>{props.children}</p>
ReactDOM.render(
<A>
<A>
<B>Hello</B>
</A>
</A>,
document.getElementById('app')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='app' />

Categories

Resources