In reactjs, what is wrappedComponent.propTypes? - reactjs

Below code example is a simplified version a component. I don't understand the code at the bottom of this component, the Case.wrappedComponent.propTypes part. I can't find relevant document about wrappedComponent on Internet as well.
Questions:
What is wrappedComponent and propTypes key in it?
What do they do?
Where can I find document for these things?
import React, { Component } from 'react';
#inject('store') #observer
export default class Case extends Component {
constructor(props) {
super(props);
this.caseId = this.props.match.params.id;
this.setOtherComment = this.setOtherComment.bind(this)
this.submitOtherComment = this.submitOtherComment.bind(this)
}
render() {
return '...'
}
}
Case.wrappedComponent.propTypes = {
store: React.PropTypes.object.isRequired,
match: React.PropTypes.object.isRequired
};

This is an API of mobx-react (with inject) and according to the DOCS
Using propTypes and defaultProps and other static properties in combination with inject
Inject wraps a new component around the component you pass into it. This means that assigning a static property to the resulting component, will be applied to the HoC, and not to the original component
........
if you want to make assertions on the data that is being injected
(either stores or data resulting from a mapper function), the
propTypes should be defined on the wrapped component. Which is
available through the static property wrappedComponent on the inject
component

Related

How to set class default props in react 18.2.0?

I saw some news about defaultProps being deprecated, but altenate solution I found was targeting function like component. But what about class component? I am new to react. Feeling like so many react things has change these years.
Oh I saw a another way is to use a deprecated package Prop-types, but it just don't feel right.
image here
Just use the static defaultProps property
Typescript example
class MyComponent extends React.Component<MyPropType,MyStateType> {
static defaultProps = {
/* Declare your default Props here */
};
Javascript example
class MyComponent extends React.Component {
render() {
// ...implement render method
}
}
// Set default props
MyComponent.defaultProps = {
/* Declare your default Props here */
};
yup, it will be deprecated in the future but only for functional components, for class-based components, it will stay as it is

Add autocomplete to Typescript/React component

I have a component (typescript + react) which I published on NPM. I want to make IntelliSense autocomplete React props for this component for me. For plain react components I used js doc, but it doesn't work here.
example of component:
class MyComp extends React.Component<
MyCompPropsInterface,
MyCompComponentState
> {...}
index file
import { MyComp } from './components/MyComp ';
export { MyComp };
If I missed something please point it and I will add it.
So I found the problem, I didn't pass my interface to the constructor.
How it should be:
class MyComp extends React.Component<
MyCompPropsInterface,
MyCompComponentState
> {
constructor(
public props: ImagePropsInterface,
)
}

Difference Between Class.contextType and Context.Consumer with working example

I am trying to understand the React context API and was going through the official docs. I will appreciate if someone can throw some more light on the following points as the official doc does not address it clearly.
What is the difference in contextType and Consumer methods to
consume the values provided by Provider? In what situation we should
use which method?
Can the value exposed by Provider in a class based component, be
used by a react hook component using useContext? I had the same
setup and i ended up converting the useContext to Context.Consumer.
I have a very straightforward setup in which i have a Provider Class
based component which is exposing some state values. The Provider
has only one children component which is also a consumer. When i use
Context.Consumer in the children to fetch the values, everything
works as expected. But when i use contextType in the children
component, i see an empty object.
ContextProvider.js
import React from "react";
import {ContextConsumer} from "./ContextConsumer";
export const TestContext = React.createContext({
count: 1,
incrCount: (count)=>{
console.log(`count value :- ${count}`)
}
});
export class ContextProvider extends React.Component {
incrCount = () => {
this.setState({
count: this.state.count + 1,
});
};
state = {
count: 5,
incrCount: this.incrCount,
};
render() {
return (
<TestContext.Provider value={this.state}>
<ContextConsumer />
</TestContext.Provider>
);
}
}
ContextConsumer.js
import React from "react";
import { TestContext } from "./ContextProvider";
export class ContextConsumer extends React.Component {
static contextType=TestContext
componentDidMount() {
const {count,incrCount}= this.context;
console.log(`count:- ${(count)}`)
console.log(`incrCount:- ${incrCount}`)
}
render() {
return (
<div>
**// BELOW CODE IS WORKING AS EXPECTED**
<TestContext.Consumer>
{({ count, incrCount }) => (
<button onClick={incrCount}>Count is {count}</button>
)}
</TestContext.Consumer>
</div>
);
}
}
App.js
import {ContextProvider} from "../../playground/ContextProvider";
const output = (
<Provider store={reduxStore}>
<ContextProvider />
</Provider>
);
ReactDOM.render(output, document.getElementById("root"));
What is the difference in contextType and Consumer methods to consume the values provided by Provider? In what situation we should use which method?
The static contextType assignment was introduced in v16.6.0 as a way to use context outside of render method. The only difference between Consumer and static context is the fact that using contextType allows you use context outside of render method too
Can the value exposed by Provider in a class based component, be used by a react hook component using useContext?
Yes the context value from Provider can be used by useContext too. However you can only make use of useContext inside a functional component and not a class component and also after v16.8.0 or react which supports hooks
P.S. You must ensure one thing that you are not causing a circular dependency by importing provider in consumer component and also the other way around
Static contextType and class.contextType
useContext
context.Consumer
are almost same the difference between them is that (1) is used in class component and
useContext is a hook and the best thing is we can use this hook multiple times in one functional component.(3) can only be used in jsx or in render(return).(1)and(2) can be used outside return.
to put it more simply:
if (functional components) { useContext }
else {
if (multiple contexts) { Context.Consumer }
else { Class.contextType }
}
// "static contextType" is experimental lets avoid

How to make components explicit in what props they accept?

Is there any known practice to make a React component constructor explicit in what arguments it accepts?
Looking at a component like below, I cannot immediately tell what do I need to pass to the constructor to initialize the component.
Instead, I need to search for specific props in the component body or check how has the component been initialized previously (if it has).
class MenuItem extends React.Component {
constructor(props) {
super(props)
}
render() {
return <div name={this.props.name}></div>
}
}
I would need something like:
class MenuItem extends React.Component {
constructor(name) {...
You can explicitly show what props your component accepts, including their types.
MenuItem.propTypes = {
name: PropTypes.string // optional string
};
You can even define them as required:
MenuItem.propTypes = {
name: PropTypes.string.isRequired // required string
};
Be sure to import the library:
import PropTypes from 'prop-types';
More information in the react docs
There is several options to type your props.
The first one is React PropTypes, it works like this:
import PropTypes from 'prop-types';
class MenuItem extends React.Component {
constructor(props) {
super(props)
}
render() {
return <div name={this.props.name}></div>
}
}
MenuItem.propTypes = {
name: PropTypes.string.isRequired
}
You just have to write the name and types of your props inside an attribute "propTypes" of your component class.
React PropTypes is a good solution when you want to type your component props.
https://reactjs.org/docs/typechecking-with-proptypes.html#proptypes
There is another solution, a Javascript Flavor like Typescript.
After setting up Typescript on your React app, you can use Typescript with your component like this:
interface IMenuItem {
name: string;
}
class MenuItem extends React.Component<IMenuItem> {
constructor(props) {
super(props)
}
render() {
return <div name={this.props.name}></div>
}
}
The advantage with Typescript is that you can type every variable, every state, every props, everything !
However, this solution is expensive in time because you have to learn well Typescript and you have to type correctly every piece of your app.
https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html
Finally, if you just want your IDE to tells you what props you can use without typing them, you can just use object destructuring on your props with a Functional Component like this:
const MenuItem = ({name}) => (
<div>{name}</div>
)
Hope this will help !
If your concerns are mainly about visibility you may be better off only writing functional components which is possible since hooks do not require any class components anymore:
const MenuItem = ({name}) => (
<div>{name}</div>
)
Buy destructuring the props in the argument list you can easily see which props are being used immediately just by looking at the function definition. From my experience writing 100's of components, functional components are usually more concise, easier to grasp and reduce boilerplate code.
Apart from that javascript is still a scripting language which means anything can be passed at runtime. PropTypes or using typescript may help you with auto-completion and type checking.

React Typescript - Context in react component class

I have created a react typescript app with create react app. I now want to have a context which I want accessible across all my components:
export const UserContext = React.createContext<{name: string}>({name: 'Foo'});
The context is linked to the state of the main app component. This state does change and therefore the value of context should also change for the components.
<UserContext.Provider value={this.state}>
<MainPage/>
</UserContext.Provider>
I have followed the doc string suggestion for how to set up in context in a component and so have this:
class MainPage extends React.Component {
static contextType = UserContext;
context!: React.ContextType<typeof UserContext>;
public render() {
return <div>{this.context.name}</div>
}
}
However this.context.name is always null. I have placed a div with it's value linked to this.state in the app component and that does show the value unlike the context. I am struggling as the code works when written in raw react / create-react-app and I was under the components where the same in #types/react?
Does anyone know how to implement context inside a component class in typescript?
Looks like the type parameter of your UserContext is slightly wrong. You need to remove the typeof.
so React.createContext<{ name: string }> instead of React.createContext<typeof { name: string }>
This works for me:
import * as React from 'react';
const UserContext = React.createContext<{ name: string }>({ name: 'test' });
export class MainPage extends React.Component<undefined, undefined> {
static contextType = UserContext;
context!: React.ContextType<typeof UserContext>;
public render() {
return <div>{this.context.name}</div>;
}
}

Resources