What is the best practice to define the properties in react? - javascript

I want to code with the best practices.
What is the best practice to define proptypes in a component class in reactjs? And why?
Inside the class:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
export default class MyComponent extends Component {
static propTypes = {
prop: PropTypes
}
render() {
return (
<div> </div>
)
}
};
or Outside the class:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
class MyComponent extends Component {
render() {
return (
<div> </div>
)
}
};
MyComponent.propTypes = {
prop: PropTypes
}
export default MyComponent;

Second option.
import React, { Component } from 'react';
import PropTypes from 'prop-types';
class MyComponent extends Component {
render() {
return (
<div> </div>
)
}
};
MyComponent.propTypes = {
prop: PropTypes
}
export default MyComponent;
Check Clean Code vs. Dirty Code: React Best Practices for reference.

Related

Enhancing from Component in React with Material-UI

I am using React and Material-UI. Is there any way to export a class estended from React.Component? I want to use some React variables like state. If this is not possible, how can I use state?
Actual code (works):
import React from 'react';
import { Typography } from '#material-ui/core';
import { makeStyles } from '#material-ui/styles';
const styles = makeStyles(() => ({
style1: {
fontSize: '12px'
}
}));
const MyComponent = () => {
const classes = styles();
return(
<Typography className={classes.style1}>Hello World</Typography>
);
}
export default MyComponent;
What I am looking for:
import React, { Component } from 'react';
import { Typography } from '#material-ui/core';
import { makeStyles } from '#material-ui/styles';
export default class MyComponent extends Component {
constructor(props){
super(props);
this.classes = makeStyles(() => ({
style1: {
fontSize: '12px'
}
}));
}
render() {
return(
<Typography className={this.classes.style1}>Hello World</Typography>
);
}
}
You are using makeStyles(), which is used when your component is a functional component. makeStyles() is a Hooks API.
If you are using the Class component, then you must be using the HOC variant, which is withStyles
Example taken from here:
import React from 'react';
import { withStyles } from '#material-ui/core/styles';
const styles = {
root: {
backgroundColor: 'red',
},
};
function MyComponent(props) {
return <div className={props.classes.root} />;
}
export default withStyles(styles)(MyComponent);
withStyles() can be used for both functional and class components unlike makeStyles(), which can only be used for functional components.
You can also use decorator syntax for HOC variant like here. But you need to use this babel plugin like mentioned in the official material-ui docs:
import React from 'react';
import { withStyles } from '#material-ui/core/styles';
const styles = {
root: {
backgroundColor: 'red',
},
};
#withStyles(styles)
class MyComponent extends React.Component {
render () {
return <div className={this.props.classes.root} />;
}
}
export default MyComponent

How to import a component to UI?

Sorry, I am new in React.js, just switched from Java and I can't understand how I shall show my map on UI. Just give me a hint
import React from "react";
import {Map, GoogleApiWrapper} from 'google-maps-react';
class TestMap extends Component {
render() {
return (
<div className="GoogleMap">
<Map google={this.props.google} zoom={14} />
</div>
);
}
}
GoogleApiWrapper({
apiKey: ({api-key})
})(TestMap);
export {TestMap, GoogleApiWrapper};
here:
import React, { Component } from 'react';
import {TestMap} from '../components/map/google/TestMap';
class Map extends Component {
render() {
return (
//???
);
}
}
export default Map;
It's a react component, render it as JSX
import React, { Component } from 'react';
import { TestMap } from '../components/map/google/TestMap';
class Map extends Component {
render() {
return (
<TestMap />
);
}
}
export default Map;
An aside, don't name your class component Map as there is already a Javascript Map object and this could be the cause for some major confusion and bugs.
EDIT
Your map is forever loading as you've exported the undecorated TestMap, i.e. it isn't decorated with the google api and props.
import React, { Component } from "react";
import {Map, GoogleApiWrapper} from 'google-maps-react';
class TestMap extends Component {
render() {
return (
<div className="GoogleMap">
<Map google={this.props.google} zoom={14} />
</div>
);
}
}
// default export the decorated component so the api-key and google prop is processed and injected.
export default GoogleApiWrapper({
apiKey: 'sLiGhTlyReDacTedApIkEy'
})(TestMap);
You need to return your component as JSX markup, Introducing JSX.
Also if you are new to react is suggest starting here, Getting Started.
import React, { Component } from 'react';
import {TestMap} from '../components/map/google/TestMap';
class Map extends Component {
render() {
return (
<TestMap />
);
}
}
Specify the component inside the return block.In your case <TestMap /> inside the return of Map component.
Firstly I am not able to understand why are you adding one more abstraction of component over your Map component. You can directly use the TestMap component you have used in the first code snippet.
Anyway, You can directly return from the Map Component.
import React, { Component } from 'react';
import {TestMap} from '../components/map/google/TestMap';
class Map extends Component {
render() {
return (
<TestMap />
);
}
}
export default Map;
Child Component
import React from "react";
import {Map, GoogleApiWrapper} from 'google-maps-react';
class TestMap extends Component {
render() {
return (
<div className="GoogleMap">
<Map google={this.props.google} zoom={14} />
</div>
);
}
}
GoogleApiWrapper({
apiKey: ({api-key})
})(TestMap);
export default TestMap;
Parent Component
import React, { Component } from 'react';
import {TestMap} from '../components/map/google/TestMap';
class Map extends Component {
render() {
return (
<TestMap />
);
}
}
export default Map;

How to test a react component with props?

I need to test a react components with props mounts ok and renders its content such as paras and divs correctly. My code can be found below or in this sandbox
I tried testing it with a default prop but that didn't work.
import React from 'react';
import test from 'tape';
import {mount} from 'enzyme';
test('testing', t => {
t.doesNotThrow(() => {
wrapper = mount(<App2 txt={ok}/>);
}, 'Should mount');
t.end();
});
And this is my component with props.
import React, { Component } from 'react';
import { render } from 'react-dom';
import Hello from './Hello';
import './style.css';
import App from './index'
export default class App2 extends Component {
constructor() {
super();
this.state = {
name: 'React'
};
}
render() {
const {txt}=this.props
return (
<div>
<p>hi {txt}</p>
</div>
);
}
}
And the outer component supplying the prop.
import React, { Component } from 'react';
import { render } from 'react-dom';
import Hello from './Hello';
import './style.css';
import App2 from './app2'
class App extends Component {
constructor() {
super();
this.state = {
name: 'React'
};
}
render() {
return (
<div>
<Hello name={this.state.name} />
<p>
Start editing to see some magic happen :)
</p>
<App2 txt={this.state.name}/>
</div>
);
}
}
render(<App />, document.getElementById('root'));
So you would do something like providing the properties yourself and ensuring that it renders with them:
test('test your component', () => {
const wrapper = mount(<App2 txt={'michaelangelo'} />);
expect(wrapper.find('p').text()).toEqual('hi michaelangelo');
});
You shouldn't worry about testing the and html elements like that, but rather the props that you pass and that they render in the right place i.e., in the p tag

Objects are not valid as a React child (found: [object HTMLDivElement])

I want to pass a value to a div with id good in my index.html but it brings this error, Objects are not valid as a React child (found: [object HTMLDivElement]). If you meant to render a collection of children, use an array instead. in TestComponent (at App.js:49)
in div (at App.js:28)
in Apps (at index.js:7)
Please what am I doing wrong
TestComponent.js
import React, { Component } from 'react';
class TestComponent extends Component {
componentDidMount(){
console.log("Great");
}
render() {
// var {test} = this.props;
return (
<p>
{this.props.test}
</p>,
document.getElementById("good")
);
}
}
export default TestComponent;
App.js
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import TestComponent from "./components/TestComponent"
class Apps extends Component {
constructor(props){
super(props);
}
render() {
return (
<div>
<TestComponent test='doyin'/>
</div>
);
}
}
export default Apps;
Index.html
<div id="good"></div>
A class Component render function shouldn't use document.getElementById, you need to use ReactDOM.render to do that
import React, { Component } from 'react';
class TestComponent extends Component {
componentDidMount(){
console.log("Great");
}
render() {
// var {test} = this.props;
return (
<p>
{this.props.test}
</p>
);
}
}
export default TestComponent;
App
class Apps extends Component {
constructor(props){
super(props);
}
render() {
return (
<div>
<TestComponent test='doyin'/>
</div>
);
}
}
ReactDOM.render(<Apps />, document.getElementById("good"))
export default Apps;
In TestComponent.js, inside render function you are trying to return two elements, <p> and document.getElementById("good"). Probably you just wanted to return <p>:
render() {
return <p>{this.props.test}</p>;
}
Also, it looks like you've mistaken React.Component.render with ReactDOM.render(element, container[, callback]) where the second argument of the functions is the container.

How to use experimental decorators and reconcile types in TypeScript?

I have the following basic component
import * as React from 'react';
import { withRouter, RouteComponentProps } from 'react-router-dom';
export interface Props { };
#withRouter
export default class Movies extends React.PureComponent<Props> {
goBack = () => {
this.props.history.goBack();
};
public render() {
return (
<div>
<button onClick={this.goBack}>Back</button>
</div>
);
}
}
I would expect withRouter to inject specific props into my component. However, when referencing this.props.history, I get this:
What is the appropriate way to use decorators which will add type definitions?
I do it this way:
import * as React from 'react';
import { withRouter, RouteComponentProps } from 'react-router-dom';
export interface OwnProps { };
type Props = OwnProps & RouteComponentProps<{}>;
#withRouter
export default class Movies extends React.PureComponent<Props> {
goBack = () => {
this.props.history.goBack();
};
public render() {
return (
<div>
<button onClick={this.goBack}>Back</button>
</div>
);
}
}

Categories