React create class confusion with extends Components - javascript

I used to do React.createClass but since I heard it's faster with extends component and since I start to play with babel now, I would like to convert stateless legacy component with the newer style.
I have this
const Main = React.createClass({
render(){
return(<h1>my title</h1>)
}
})
so what's the 'newer' syntax for above code?
is it like this?
const Main = () => {
render(){
return(<h1>my title</h1>)
}
}
Then when to use React.component?
class Main extends React.Components() {
render(){ return(<h1>something</h1>}
}

There is not performance difference between using
const Main = () => {
return(<h1>my title</h1>)
}
or
class Main extends React.Component {
render(){ return(<h1>something</h1>}
}
given they receive the same props, however the react creators suggest that performance improvements will be made in future. So in short,
Use the first approach, which is a functional component approach when your component only takes in props and renders the result. However use the ES6 class based approach, when your React component has more functionality and handles states.
In your case you are just rendering the component so a functional component approach will be best suited for you

Both of your example is correct. Just that the extends Component should be without s and need to import React, { Component } from 'react'; at the top.
const Main = () => {
return(<h1>my title</h1>)
}
You generally want to use the above example when it is does not need any lifecycle methods. This are refer to as Pure component that will always behave the same when given the same props. It also does not keep state.
class Main extends React.Component() {
componentWillMount() {
console.log("I can be not pure");
}
render(){ return(<h1>something</h1>}
}
The above are Component that could manage state and use lifecycle methods.
Usually to decide what to use, I always start with a pure component. When continue developing, I discover that I have to use state or lifecycle methods, I would then turn it to a component.

Related

useContext only works in stateless functional component

I'm trying to get to grips with the new useContext function in React. Works great in stateless functionality components. For example:
import React from 'react';
import LocaleContext from '../LocaleContext';
const Link = ({ text, url }) => {
const locale = useContext(LocaleContext);
return (
<a href={`/${locale}/${url}`}>
{text}
</a>
);
};
export default Link;
I also want to use useContext in stateful components, and even non React functions, but when I do so, I get the following error:
Hooks can only be called inside the body of a function component.
The message seems simple enough to understand, but is this really true? I can only use it in a stateless functional component? If so, it seems kind of pointless to me, because it's super easy to use a simple HOC or the traditional method of:
<Locale Consumer>
{locale => (
...
)}
</LocaleConsumer>
So what gives here? I have the latest version of every package in my project. Not sure if it matters but I'm developing a NextJS site here.
If you really want to use classes (i actually came from Angular and i still prefer use classes) you can workaround easily like that:
class ComponentImpl extends React.Component<any> {
constructor(props?) {
super(props);
}
render() {
return (
<div>
CounterButton: <button onClick={() => {this.props.appContext.setCount(this.props.appContext.count + 5)}}>App Counter + 5</button>
</div>
)
}
}
export function Component() {
let appContext = useContext(AppContext);
return <ComponentImpl appContext={appContext}></ComponentImpl>
};
And you just use it: <Component></Component>
The problem is what the error says. React hooks aren't available in class components. Due to differences between class components and function components, hooks cannot be used with the former.
As the documentation says,
Hooks let you use more of React’s features without classes. Conceptually, React components have always been closer to functions. Hooks embrace functions, but without sacrificing the practical spirit of React. Hooks provide access to imperative escape hatches and don’t require you to learn complex functional or reactive programming techniques.
Hooks are supposed to address common use cases that are specific to class components which couldn't be previously implemented with stateless functional components alone. Functional components aren't stateless since React 16.8 and are allowed to have a state and trigger own updates.
As for useContext hook,
When the provider updates, this Hook will trigger a rerender with the latest context value.
It would be messed up in class component due to difference between functional and class components. Component function is called each time the component is rendered:
const Foo = props => {
const context = useContext(Context);
// use context
}
There's no place in class component that would behave the same way except render function. And if lifecycle-specific tasks go to render function, this means that a class was a wrong choice, and class component needs to be refactored to a function. A counterpart to useContext in class components is contextType, which is currently restricted to single context.
For multiple contexts it's still required to receive them through context Consumer inside render, or as props from higher-order component wrapper:
const contextsHOC = (contexts = {}) => Comp => (
props => {
const contextProps = {};
for (const prop in contexts) {
// eslint-disable-next-line react-hooks/exhaustive-deps
contextProps[prop] = React.useContext(contexts[prop]);
}
return <Comp {...props} {...contextProps}/>;
}
);
#contextsHOC({ bar: BarContext, baz: BazContext });
export default class FooComponent extends Component {
// contexts are mapped to this.props.bar and this.props.baz
...
}
// or
class FooComponent extends Component { ... }
export default contextsHOC({ ... })(FooComponent);
Passing contexts as props allows for additional optimization with PureComponent or shouldComponentUpdate.
useContext is a hook that consumes a context and can only be used in functional components.
If you want to consume context in class components, you will need to look at alternative methods such as Consumer Component, official docs for this here

Prop-types checking in react component

I have a couple question about prop-types in React:
1. when should we use react props-type checking in component, do we have to use it in all component with props passed in ?
2. can props-type checking be applied in both stateless component and class component ?
You can use prop-types in whatever components you want prop validation to occur. It doesn't have to be used in every component that uses props, although it's generally a good idea to do so.
For a class component, you can do:
class Component extends React.Component {
static propTypes = {
// prop types here
}
// component stuff
}
For a functional component, you can do:
const Component = (props) => {
// component stuff
}
Component.propTypes = {
// prop types here
}
When should you use them? Whenever you want. Might be nice to add them if you're sharing these components with other developers (at work or on npm)
Can you use them in both functional and class components? Yes.

React - How to access props without using constructor

Note: I encounter this specific problem using React Native, but I guess this goes for React in general as well.
I have a react component built using React.Component.
I don't need to set state, but I do have props. My proposed syntax was as follows:
class Header extends Component {
constructor(props) {
super(props);
}
render() {
return <div>{this.props.title}</div>;
}
}
I understand I can use a function to construct this component, like this:
const Header = (props) => {
return <div>{props.title}</div>;
}
But I prefer the former, because my component will grow, might have state etc, and I just want to keep all my components built in a similar fashion.
Now, my linter complains about having a useless constructor, but how else do I access the props while keeping a class constructor instead of a function constructor?
If you want to use this.props in the constructor, you need to pass props to super. Otherwise, it doesn't matter because React sets .props on the instance from the outside immediately after calling the constructor.
So just simply remove constructor() if useless
you can access props without constructor in a class using "this", like this:
class XXXXXX extends React.Component {
render() {
return (
<div>{this.props.value}</div>
)
}
}

React ES6 components using arrow functions

Very new to react,
I have a class like:
export const Checkbox = ({ label, className }) => {
....
....
return(
.............
.............
);
}
In such a class how can I specify add a componentDidMount and componentWillReceiveProps?
Edit:
I have a layman's doubt, which is the correct way to create a wrapper react component for checkbox? functional component or by extending from Component? If I create a Checkbox wrapper component for others to use, will it be possible for them to connect to a store (say redux) from their pages?
Thanks,
Santhosh
You can't.
These are functional components and do not support React's lifecycle methods.
If you want to use React's lifecycle methods, you need a class that inherits from React.Component
See example below.
class Example extends React.Component {
componentDidMount(){
//code here
}
}
Here is a good answer explaining the differences and when to use functional over class components.
UPDATE from React 16.8
Lifecycle methods can now be used with the introduction of hooks.
If you wished to implement componentDidMount you would use the useEffect hook and pass an empty array as the second argument. An example would look like as follows.
const Example = () => {
React.useEffect(() => {
// do stuff here
}, []);
}
You can't.
If you want to use React's lifecycle methods, you need a class that inherits from React.Component.
export class Checkbox extends React.Component {
componentDidMount() {
....
}
render() {
const { label, className } = this.props;
....
}
}
You cannot. You should create a class that extends PureComponent or Component if you need lifecycle methods.

Difference between decorators and mixins in react

I am a beginner to react and finding myself confused between mixin and decorators. Can somebody elaborate? Thanks.
They both extend and/or override methods of the React Component. They are used to share common functionality between components, in places where extending a class would not work and is not intended.
An example would be the PureRenderMixin, which overrides the shouldComponentUpdate method and compares the props of a component to decide, if a rerender should be executed.
However, mixins are deprecated and do not work with the ES6 syntax of React anymore. Your options are either to use inheritance or decorators to achieve the same result.
Example
Here is an example of the (kind of) PureRenderMixin, using a decorator. Also I used Immutable.js.
// pure.js
import React from 'react';
import assign from 'object-assign';
import {is} from 'immutable';
/**
* Pure Render Decorator
* #param props
* #returns {function()}
*/
export default (...props) => (Component) => class PureComponent extends React.Component {
shouldComponentUpdate(nextProps) {
if (!props.length) {
props = Object.keys(nextProps);
}
for (let i = 0, l = props.length; i < l; i++) {
if (!is(nextProps[props[i]], this.props[props[i]])) {
return true;
}
}
return false;
}
render() {
return React.createElement(Component, assign({},
this.props,
this.state
));
}
}
The general usage of the decorator would be #pure(params).
params can contain the name of the props or can be empty. In the decorator you see the ...props as a parameter. This is where the params are passed in.
The parameter Component of the inner function gets the React Component passed in, on which you use the decorator.
You can use the decorator in your component as follows:
import React from 'react';
import pure from './pure.js';
#pure('myProp', 'anotherProp')
export default MyComponent extends React.Component {
static propTypes = {
myProp: React.PropTypes.any,
anotherProp: React.PropTypes.any
}
render() {
return <p>I only re-render, when my props changed.</p>;
}
}
What does it do?
The decorator overrides the shouldComponentUpdate method of the component. Everytime the React Component calls its shouldComponentUpdate method, it now uses the one provided in the decorator.
The decorator itself compares the props of the Component to the next props that it is going to receive. Only if the props change, the component will update.
This is nice, because it prevents unnecessary rendering - that's great for performance!
You see, decorators are basically functions that take parameters (such as the React Component) and modify them in order to make code reusable. It takes a bit of getting used to, but its no rocket science. :-)
If there are any more questions, please feel free to ask!

Categories

Resources