Lint complains about missing prop coming from HOC - reactjs

I'm using the package react-translate to localise my app.
import React from 'react';
import { translate } from 'react-translate';
class Hello extends React.Component {
render() {
return (
<div>
{this.props.t('test_string')}
</div>
);
}
}
export default translate('Hello')(Hello);
In the snippet above, translate is a High Order Component, that adds the function t to the properties of Hello.
Everything works fine but lint keeps complaining because t is not in the propTypes.
error 't' is missing in props validation react/prop-types
Is that normal? I guess I'm doing something wrong but I cannot tell what...
Edit:
As #stevejay says, I could add the t to my propTypes but I don't like this solution because - from my total ignorance in react - 1) t is not a property of the component itself, nor something I want to manually pass and 2) I have to add the property to all the models where I have already added the HOC and it seems redundant

To silence the linter, you need to just add propTypes to your Hello component:
import React from 'react';
import PropTypes from 'prop-types';
import { translate } from 'react-translate';
class Hello extends React.Component {
...
}
Hello.propTypes = {
t: PropTypes.func.isRequired
}
Any props that a component you create uses should be declared in that way.

Related

"class X extends React.Component" is not a valid JSX element

I am using a library component which is declared this way:
import React, { ReactNode } from 'react';
export declare class Splide extends React.Component<SplideProps> {
When trying to use it in my projects, typescript throws the following error:
TS2786: 'Splide' cannot be used as a JSX component. Its instance type 'Splide' is not a valid JSX element. Type 'Splide' is missing the following properties from type 'ElementClass': context, setState, forceUpdate, props, and 2 more.
If I ignore the error it seems the component works properly once deployed, so I'm guessing it's a typescript issue
I could confirm that modifying the library to be written this way fixed the issue:
import React, { ReactNode, Component } from 'react';
export declare class Splide extends Component<SplideProps> {
as does this:
import * as React from 'react';
export declare class Splide extends React.Component<SplideProps> {
However I don't really want to keep a modified version of the library locally, and since nobody else has mentioned that issue it's probably a problem with my setup. I could just #ts-ignore every usage of that component or create a middleware component that extends and fixes that component but again, not great practices.
Some additional points I checked:
I saw mention of using resolutions in package.json to enforce #types/react and react versions, but it didn't work
I double checked inside react, and the class Component is inside the namespace React so as far as I can tell React.Component should work

Connection between Bootstrap componments reactstrap and react.Component

I'm new to Rect. I'd like to ask perhaps a most basic question since I can't find the relavent documentation or a answer on Google.
Following is the first 3 lines of typical react code:
import React, { Component } from "react";
import {
Button,
Modal,
} from "reactstrap";
export default class CustomModal extends Component {
...
}
What is the connection between Bootstrap componments imported on the second line from reactstrap and the Component class in react(that is, react.Component)? Why a CustomModal subclass from react.Component instead of reactstrap.Modal? is react.Component a sort of abstract class and reactstrap.Modal concret class extending react.Component?
Basically, yes. You extend React.Component to create your own custom class-based React components. The others that you are importing are from libraries where the library author has already created the components. Note that you can also create custom function-based React components where you don't extend React.Component. I would recommend reading through the React.Component documentation.
To your question about how it relates to CustomModal, you would use Modal as a component within CustomModal. For example:
import React, { Component } from "react";
import {
Button,
Modal,
} from "reactstrap";
export default class CustomModal extends Component {
...
render() {
return <Modal />;
}
}
Note that this example is just to give you the idea of how to use an imported component in your own custom component. It is not necessarily how to use reactstrap.Modal itself.

constructor vs babel returns an error anything I do without using babel.

I'm learning react and on the course they are using the create-react-app, I'm trying to code along but somehow I don't think that babel is working for me so I need to use the constructor and super even though the course I'm following isn't. I have managed to follow along until I got to this lesson that used static.
the code the lesson gives is:
import React, { Component } from 'react'
import PropTypes from 'prop-types'
class Xpto extends Component {
static propTypes = { //some props }
}
render() {
// some logic
}
My code is:
import React, { Component } from 'react'
import PropTypes from 'prop-types'
class Xpto extends Component {
constructor() {
super()
static propTypes = { //some props }
}
render() {
// some logic
}
}
The issue is that when I use this, it returns this error:
Syntax error: static is a reserved word in strict mode (10:4)
if I move it outside of the constructor but inside the class it says that propTypes isn't defined and if i remove static and use this.propTypes it works but returns an error in the console saying to use static.
I don't get what is happening or how to resolve this situation. Asked a friend that has done some work with React and he told me he didn't know either to get babel working and use the course approach but I'm stubborn and like to know what is going on so I'm reaching out to you.
Thanks in advance for any help.
Try defining the propTypes outside of the class:
class Xpto extends Component {
constructor(props) {
super(props);
}
render() {
const { name = 'Dan Abramov' } = this.props;
return <div>{name}</div>;
}
}
// You can define propTypes and defaultProps here
Xpto.propTypes = {
name: PropTypes.string
};
If that does work, try removing the constructor.
If it doesn't work, though, post the error and we'll go from there.

TS2339: Property 'props' does not exist on type 'Home'

I have a very basic program of react with tsx, I am getting an error which I am not able to figure out why
import React from 'react';
// import {connect} from 'react-redux'
export class Home extends React.Component {
render(){
console.log(this.props)
return (
<div>Working</div>
)
}
}
import * as React from 'react'
import * as ReactDOM from 'react-dom';
import {Home} from './Components/Home.component'
class App extends React.Component<any,any>{
render(){
return(
<Home value="abc" />
)
}
}
ReactDOM.render( <App />, window.document.getElementById("app"))
git clone this for code
After pulling down your repo and inspecting it, I realised that you do not have react typings for typescript.
Typings is the simple way to manage and install TypeScript definitions
Adding this line
"#types/react": "^16.0.25" // or another version you prefer
to the package.json and running npm i or yarn if you are using yarn as a package manager, one more time, solved the issue.
Try it out and let me know if this solves it on your side :)
PS: TypeScript requires you to describe the shape of your objects and your data. If you look at the other answer I provided earlier, it was pretty much a long and complicated version of You need to specify a type that describes your props and need to pass this to the component in question
Typescript needs to know the shape of the props and state passed to a component. If you really want to stop Typescript from enforcing typings in your component (which, btw, defeats the whole purpose of using Typescript), then, the component that needs access to the props or state passed to it has to specify the type or shape so to speak, as any. That is, your component will look something like this
export class Home extends React.Component<any, any>
instead of
export class Home extends React.Component
which btw, is an incorrect way of extending a class if that class expects props and/or state.
Passing any type for props and state means that the component in question must accept any kind of shape (type) for both props and state.
Try this
import * as React from "react";
import * as ReactDOM from 'react-dom';
export class Home extends React.Component<any, any> {
render() {
console.log(this.props)
return (
<div>Working</div>
)
}
}
class App extends React.Component{
render() {
return (
<Home value="abc" />
)
}
}
ReactDOM.render(<App />, document.getElementById("app"));
and everything should work as expected because you got Typescript out of your way in terms of type-checking for you.
You can also view the demo here
If you actually wanted to enforce the shape (type) of the props and/or state you would then have to define these shapes with, usually, an interface or inline type annotation. Here is an example of the same code above that enforces the shape of the props using the former method:
import * as React from "react";
import { render } from "react-dom";
interface Props {
value:string,
name:string
}
export default class Home extends React.Component<Props>{
render() {
console.log(this.props)
return (
<div>Working. The props values are: {this.props.value} {this.props.name}</div>
)
}
}
class App extends React.Component {
render() {
return (
<Home value="abc" name="def"/>
)
}
}
render(<App />, document.getElementById("root"));
Now, here you could never be able to add any other prop to the Home component that is not defined in the Props interface.
For example doing something like:
<Home value="abc" name="DEF" somethin="else"/>
would not compile because somethin is not defined in the interface that is used by the Home component.
To enforce the shape of the state you'd have to do the same thing as for the props, i.e. define a contract (interface).
Also, note that you still need to access your props via this NOT Props as this is just a type definition of the structure not holder of the values themselves.
You can view the demo for this alternative here

Why creating a new Component class for redux connect?

In reference this coding pattern:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import Thing from '../components/Thing';
class ThingContainer extends Component {
render() {
return <Thing {...this.props} />;
}
}
function mapStateToProps(state) {
...
}
export default connect(mapStateToProps)(ThingContainer);
So it 1) imports a component(Thing), 2) creates another component (ThingContainer which is technically not a container) class to render that first component, and lastly using connect to finally export the container.
What's the difference with skipping step 2 above, and simply using the imported component(Thing) directly to export the container?
Yeah, that file looks like it's somewhat unnecessary. The class ThingContainer component does nothing but forward props to <Thing>, which is exactly what the wrapper components generated by connect do already. So, that's useless - the file should just do export default connect(mapState)(Thing), and it would work exactly the same without the extra ThingContainer definition.

Resources