Stateful and Functional stateless components - javascript

How to convert Stateless functional components to stateful component in order to use lifecycle methods and passing props to it like Stateless Component.
( export default JobCard = (props) => {
............
}
)
I need to convert this to stateful component in order to use life-cycle method and pass props to the return function like how props is passed here. Thank you in advance.

You can do it like this:
export default class JobCard extends React.Component {
render() {
// here you can access props passing down from
// parent components like: this.props
return (
<div>
Hi, I'm a super smart component!
</div>
);
}
}

Related

Converting functional component to class based component

I need to convert a functional component to a class based component. I am fairly new to React but I have tried to convert the component. I get the error - ReferenceError: Cant find variable: Props
My question is, where do I add props which was present in the class based component to make the conversion work ?
The class based component which is a modal with a form triggered from a parent component,this works well. The form uses state variables which dont work in a class based component so I need to convert the current functional component to a class based component. I'm using version 16.6.3 of React because other packages do not work with newer versions of React-Native so I cant use hooks with this version.
Functional component
const ShowModal = props => (
<Modal
visible={props.display}
animationType="slide"
onRequestClose={() => console.log("closed")}
>
...Other stuff in here.
</Modal>
);
export default ShowModal;
Class based component
export default class ShowModal extends Component {
state = {
};
render() {
return (
...Other stuff in here
);
}
}
I get the error - ReferenceError: Cant find variable: Props
In class based components props is exposed in the main scope of the class. You should read it using this keyword
class Component extends React.Component{
render(){return this.props.value}
}
I presume you want to use State, as the reason for moving to a Class component. Instead I suggest to use React Hooks which is the newest and elegant approach.
const ShowModal = props => (
const [state, setState] = React.useState({});
<Modal
visible={props.display}
animationType="slide"
onRequestClose={() => console.log("closed")}
>
...Other stuff in here.
</Modal>
);
React Hooks: https://medium.com/frontmen/react-hooks-why-and-how-e4d2a5f0347

Pass React Props to a Separate JS File

I'm trying to pass props for width from a parent component to a child JS file, but cannot seem to get the props value in the child JS file. The parent is the following:
import React from 'react';
import Child from './Child';
export default class Home extends React.Component {
state = {
width: 1000
}
render(){
return(
<div>
<Child width={this.width} />
</div>
);
}
}
The separate child JS file is the following:
import React from 'react';
const svgWidth = 650, // Load prop here
svgHeight = 340;
What I've tried is the following but is not working for me:
import React from 'react';
const Child = (props) => {
console.log({props.width}); // Getting an error that ',' is expected
return {props.width};
}
Can someone please help me with passing the width value from ?
Change to the following, as you should access state through this.state, like so:
<Child width={this.state.width} />
Either use the prop drilling, hence pass the values from parent to child as a prop.
But exact answer to your question will be :
create a blank object in separate js file and export it and then in componentDidMount populate that object with the props which you want to save. Next time when ever you will use that object anywhere in normal js file you will get the props.
If you intend to pass props to a child component, then I would start with the following:
import React from 'react';
import Child from './Child';
export default class Home extends React.Component {
constructor(props) { // don't forget to add a constructor
super(props); // also required
this.state = {
width: 1000
}
}
render(){
// to pass state use {this.state}
return(
<div>
<Child width={this.state.width} />
</div>
);
}
}
However, if that is not the case and instead you want to export state to a separate js file (that may not even be a React component), then you may have to look at export syntax. I am struggling with a similar problem right now and I already tried what Vikash Kumar suggested without success. This is explained on this question but I was not successful with that approach either: export function inside react component or access state in same file outside of component

ReactWrapper::setProps() error when attempting to set Redux props in component for Jest/Enzyme test

I'm writing a unit test for a React component that is connected to Redux. One of the functions is the component is that it displays data if questionReducer.showquestions == true. I have attempted to re-create this functionality in the component by setting props with wrapper.setProps({ questionReducer: { showquestions: true } }). However, when I attempt this approach, I get the error:
ReactWrapper::setProps() expects a function as its second argument
How can I properly set the props for the connected Reducer in the component I am testing?
You should test the component alone, without being connected to Redux. That allows you to give props directly to component.
Example:
export class Component_ extends React.Component {
// your component logic here
}
const mapStateToProps = {
showQuestions: questionReducer.showquestions
}
const Component = connect(mapStateToProps)(Component_)
export default Component
And then in test you can just do this
const wrapper = shallow(<Component_ showQuestions={true} />

Is it possible to create a React component interface?

I have the following react component:
class Cmp extends React.Component {
render () {
return <h3>{this.props.title}</h3>;
}
}
But I would like to expose or say to the consumer of my component to use it with a title otherwise it does not work the component.
Consumer would use it like
<Cmp title='Some fancy title' />
I need the consumer of my component to know that he should provide a title otherwise the component does not have any sense.
You can use PropTypes and set it to isRequired. You can also check if the prop is set at componentWillReceiveProps() and throw your error.
If you return null from a render method, nothing is rendered. You could use this knowledge to conditionally check if the prop is passed, and return null if the prop is not passed. The advantage here over using componentWillReceiveProps() is that you could use a functional component rather than a class component.
In rare cases you might want a component to hide itself even though it
was rendered by another component. To do this return null instead of
its render output.
Preventing Component from Rendering
Realistically you would also use PropTypes.
Cmp.propTypes = {
title: PropTypes.string.isRequired
};
Short Example
import React from 'react';
import PropTypes from 'prop-types';
const Cmp = (props) => props.title ? <h3>{props.title}</h3> : null
Cmp.propTypes = {
title: PropTypes.string.isRequired
}
export default Cmp;

ESLint - Component should be written as a pure function (react prefer/stateless function)

ESLint is giving me this error on a react project.
Component should be written as a pure function (react prefer/stateless
function)
It points to the first line of the component.
export class myComponent extends React.Component {
render() {
return (
//stuff here
);
}
}
How do I get rid of this error?
Two choices.
Temporarily disable warning
(Untested; and there are multiple ways to do this.)
// eslint-disable-next-line react/prefer-stateless-function
export class myComponent extends React.Component {
...
}
Use a pure stateless component
The return value is what will be rendered (e.g., you're basically writing class-based component's render method:
export const myComponent = () => {
return (
// JSX here
)
}
(Or use non-ES6 notation if that's your thing.)
For components like this with no other supporting logic I prefer the implicit return, e.g.,
export MyComponent = () =>
<div>
// Stuff here
</div>
This is a matter of preference. I would say that you should follow React naming conventions, though, and keep all components starting with an upper-case letter.
ESLint may complain about missing parens around a multi-line JSX expressions, so disable that rule or use parens.
If you need props, they're passed in as the argument to the function:
const MyComponent = (props) =>
<div>
<Something someProp={props.foo} />
</div>
export MyComponent
And you can destructure in the parameter as usual for convenience:
const MyComponent = ({ foo }) =>
<div>
<Something someProp={foo} />
</div>
This can make the implicit return a little easier if you were using local vars. You'll get an ESLint warning about missing PropTypes unless you declare them; since it's not a class you cannot simply use static propTypes in the class, they must be attached to the function (which many people prefer anyway).
Add constructor() like:
exports class myComponent extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<div>Hello</div>
);
}
}
Write your component as a stateless function:
export myComponent = () => { //stuff here };
There are actually two styles of defining components in React: Functional components (which are just functions from props to a React component) and class components.
The main difference between them is that class components can have state and lifecycle methods such as componentDidMount, componentDidUpdate, etc.
Whenever you don't need state of lifecycle methods, you should write your component as a stateless function, as stateless components are in general easier to reason about.
To write a functional component, you write a function that takes a single argument. This argument will receive the component's props. Consequently, you don't use this.props to access the component's props - you just use the function's argument.
If you rely on props, then there is a better (somewhat arguable, as of this writing) way to fix this error without writing out Stateless functions - by writing a PureComponent and using this eslint rule [source]:
"react/prefer-stateless-function": [2, { "ignorePureComponents": true }],
With above rule, the following snippet is valid (since it depends on props)
class Foo extends React.PureComponent {
render() {
return <div>{this.props.foo}</div>;
}
}
React team plans to build optimizations around SFC but they are not there yet. So until that happens, SFCs will not offer any benefits over PureComponents. In fact, they will be slightly worse as they will not prevent wasteful renders.
You will get this error only when your class does not have any life cycle method or constructor.
To solve this either you have to disable the lint property or make it as a pure function or create constructor for the class.
const myComponent = () => {
return (
//stuff here
);
};
export default myComponent;
And in app.js file just import this component as we do for class like
import myComponent from './myComponent.js'
and call as
<myComponent />
It will work for sure.
export class myComponent extends PureComponent {
...
}
If all you're doing is rendering a jsx template, and not declaring state with constructor(props), then you should write your component as a pure function of props, and not use the class keyword to define it.
ex.
export const myComponent = () => (
// jsx goes here
);
you need to add constructor(props)
export class myComponent extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
//stuff here
);
}
}

Categories