I have a React component that uses default props:
class MyComponent extends Component {
constructor(props) {
console.log('props', props);
super(props);
// rest of code here
}
MyComponent .defaultProps = {
__TYPE: 'MyDateRange',
};
When I use the component, without passing any props, the console log of props shows the default props, like it should.
Now, when I want to pass an additional prop (a function in this case), like this:
<MyComponent onEnterKey={() => console.log('snuh')}/>
The console log of props only shows the onEnterKey function.
What do I have to do to allow MyComponent to use the default props and accept a function? I've tried adding another argument to the constructor of MyComponent, but that doesn't work.
I tried and this is working :
import React from "react";
import { render } from "react-dom";
class MyComponent extends React.Component {
constructor(props) {
console.log("props", props);
super(props);
}
render() {
return null;
}
}
MyComponent.defaultProps = {
__TYPE: "MyDateRange"
};
render(
<MyComponent onEnterKey={() => console.log("snuh")} />,
document.getElementById("app")
);
You can see it here : https://codesandbox.io/s/wkw0k0j5o8
You can put the defaultProp on the class outside of the constructor like this:
class MyComponent extends Component {
constructor(props) {
console.log("props", props);
super(props);
}
render() {
return <div> test </div>;
}
}
MyComponent.defaultProps = {
__TYPE: "MyDateRange"
};
Alternatively, you can have defaultProps be a static property on the class:
class MyComponent extends Component {
static defaultProps = {
__TYPE: "MyDateRange"
};
constructor(props) {
console.log("props", props);
super(props);
}
render() {
return <div> test </div>;
}
}
Related
2 components :- ClickCounter, mouseHoverCounter !
1 HOC component to do the counting work.
earlier I was counting the click and mouse hover by writing separate counter method in each component(cliccounter,mousehovecounter),
but
now, I'm trying to pass the component into hoc counter & get the new component with only one change , where I'm passing a props to originalComponent and returning it to see the behavior but its now working...
import React, { Component } from 'react'
import updatedComponent from './hocCounter'
class ClickCounter extends Component {
constructor(props) {
super(props)
this.state = {
counter:0
}
}
ClickCounterHandler = () =>{
this.setState((prevState)=>{
return {counter:prevState.counter+1}
})
}
render() {
const count=this.state.counter
return (
<div>
<button onClick={this.ClickCounterHandler}>{this.props.name} Clicked {count} Times</button>
</div>
)
}
}
export default updatedComponent(ClickCounter)
import React, { Component } from 'react'
import updatedComponent from './hocCounter'
class HoverMouseCounter extends Component {
constructor(props) {
super(props)
this.state = {
counter:0
}
}
MouseOverCounter(){
this.setState((prevState)=>{
return {counter:prevState.counter+1}
})
}
render() {
const count=this.state.counter
return (
<div>
<h1 onMouseOver={this.MouseOverCounter.bind(this)}>{this.props.name} Hovered For {count} Time(s)</h1>
</div>
)
}
}
export default updatedComponent(HoverMouseCounter)
import React from 'react'
const updatedComponent = originalComponent => {
class newComponent extends React.Component {
render(){
return <originalComponent name='Harsh'/>
}
}
return newComponent
}
export default updatedComponent
In App.js, I'm returning
<ClickCounter></ClickCounter>
<HoverMouseCounter></HoverMouseCounter>
this only !
Check the error in the console,
index.js:1 Warning: <originalComponent /> is using incorrect casing. Use PascalCase for React components, or lowercase for HTML elements. at originalComponent
This means You are using the small letter in originalComponent
React components are expected to start with a capital letter
Try this in you HOC component
import React from 'react'
const updatedComponent = OriginalComponent => {
class NewComponent extends React.Component {
render(){
return <OriginalComponent name='Harsh'/>
}
}
return NewComponent
}
export default updatedComponent
Can you help me in changing this React stateless functional component to React class based component including the withRouter and history object as given?
const Menu = withRouter(({history}) => (
<AppBar>
</AppBar>
))
export default Menu
class Menu extends React.Component {
render() {
// you can use this.props.history anywhere in the class
const { history } = this.props;
return <AppBar>...</AppBar>
}
}
export default withRouter(Menu);
First, create your class component and then, create a constructor for the class. You can then define the states required inside the constructor, something like this-
export default class Menu extends React.Component {
constructor(props) {
super(props);
this.state = {
SomeVar: xyz,
AnotherVar: undefined
}
}
render() {
return withRouter(({history}) => (
<AppBar> </AppBar>
));
}
}
I have an ant design Table component that I want ref to be attached to.
I want to be able to use the tableRef in HOC withCustomPagination's lifecycle componentDidUpdate method.
Following the React Docs Forwarding Refs, that I could not clearly comprehend. I could cook up the following code:
App.js
import WrappedTable from '/path/to/file';
class App extends React.Component {
render() {
const tableRef = React.createRef();
return (
<WrappedTable ref={tableRef} />
)
}
}
Table.js
import withCustomPagination from '/path/to/file';
class Table extends React.Component {
constructor(props) {
super(props);
}
render() {
<TableContainer ref={this.props.forwardedRef} />
}
}
const WrappedTable = withCustomPagination(Table);
export default WrappedTable;
withCustomPagination.js
import CustomPagination from 'path/to/file';
const withCustomPagination = tableRef => Component => {
class WithCustomPagination extends React.Component {
constructor(props) {
super(props);
this.state = {
rows: 1,
dataLength: props.dataLength,
}
}
componentDidUpdate() {
tableRef.current.state ..... //logic using ref, Error for this line
this.state.rows ..... //some logic
}
render() {
const { forwardedRef } = this.props;
return (
<Component {...this.state} ref={forwardedRef} />
<CustomPagination />
)
}
}
return React.forwardRef((props, ref) => {
return <WithCustomPagination {...props} forwardedRef={ref} />;
});
}
export default withCustomPagination;
After debugging, I find that forwardedRef is always null.
Your issue is happening in your HOC:
here
const withCustomPagination = tableRef => Component => {
You need to remove that parameter. The way to access to the ref prop is simply in your componentDidUpdate method like forwardedRef prop e.g:
import CustomPagination from 'path/to/file';
const withCustomPagination = Component => {
class WithCustomPagination extends React.Component {
constructor(props) {
super(props);
this.state = {
rows: 1,
dataLength: props.dataLength,
}
}
componentDidUpdate() {
//You got the ref here
console.log(forwardedRef.current)
}
render() {
const { forwardedRef } = this.props;
return (
<Component {...this.state} ref={forwardedRef} />
<CustomPagination />
)
}
}
return React.forwardRef((props, ref) => {
return <WithCustomPagination {...props} forwardedRef={ref} />;
});
}
export default withCustomPagination;
Also somethings to have in account are:
You should not create the ref in the render method because this method is raised every time you set a state. I recommend you to do it in the constructor:
import WrappedTable from '/path/to/file';
class App extends React.Component {
constructor(){
super();
this.reference = React.createRef();
}
render() {
return (
<WrappedTable ref={this.reference} />
)
}
}
Also in you HOC render only one child or use React.Fragment. Besides do not forget the send the rest properties:
const withCustomPagination = Component => {
class WithCustomPagination extends React.Component {
constructor(props) {
super(props);
this.state = {
rows: 1,
dataLength: props.dataLength,
}
}
componentDidUpdate() {
//You got the ref here
console.log(forwardedRef.current)
}
render() {
// Do not forget to send the rest of properties here like:
const { forwardedRef, ...rest } = this.props;
return (
<React.Fragment>
<Component {...this.state} ref={forwardedRef} {...rest} />
<CustomPagination />
</React.Fragment>
)
}
}
return React.forwardRef((props, ref) => {
return <WithCustomPagination {...props} forwardedRef={ref} />;
});
}
export default withCustomPagination;
EDIT:
Add the reference of the ref prop
import withCustomPagination from '/path/to/file';
class Table extends React.Component {
constructor(props) {
super(props);
this.reference = React.createRef();
}
render() {
<TableContainer ref={this.reference} />
}
}
const WrappedTable = withCustomPagination(Table);
export default WrappedTable;
To access the tableRef in HOC withCustomPagination, I removed const tableRef = React.createRef() from App.js and the corresponding ref = {tableRef} lines.
I pass tableRef to HOC, curried, withCustomPagination(tableRef)(NewGiftCardTable). I also removed all the Forwarding Refs logic in HOC, this I did because I needed access to tableRef only in HOC and not in App.js.
Added above removed lines to Table.js:
import withCustomPagination from '/path/to/file';
const tableRef = React.createRef();
class Table extends React.Component {
constructor(props) {
super(props);
}
render() {
<TableContainer ref={tableRef} />
}
const WrappedTable = withCustomPagination(tableRef)(Table);
export default WrappedTable;
I`m creating a react dynamic dialog where you can add functionality to the Dialog.
One way of doing this was with Composition, but I did not manage to do this via composition.
I`m not very experienced on React, so this was my first approach
I got my Modal component, and the modal has
export default class KneatModal extends React.Component {
constructor() {
super();
this.state = {
open: false
}
this.components = [];
I would add components like this
import CommentField from '../../../Modal/ModalContents/CommentField.jsx'
export default class DoApprove extends React.Component {
constructor() {
super();
}
componentDidMount() {
this._buildDialog();
}
_buildDialog() {
console.log("Building the Dialog");
this.modal.components.push(CommentField);
}
In that modal renderer, i have
<ModalContent components={ this.components } />
Then i the final renderer in ModalContent i try to render all attached components
render() {
var list = this.props.components.map((Component, key) => <Component/> );
return (
<div className='modal-contents'>
{list}
</div>
)
}
But the render method does not seems to work, i`ve tryed callin Component.render() instead of the component tag, but still could not make the sub-components render. =(
Would apreciate any help. Thanks
To be even more specific, this resumes on what im attempting
import PropTypes from 'prop-types';
import React from 'react';
import MyComponent1 from './MyComponent1.jsx'
import MyComponent2 from './MyComponent2.jsx'
export default class KneatModalContent extends React.Component {
constructor() {
super();
this.components = [MyComponent1, MyComponent2];
}
render() {
return (
<div className='modal-contents'>
{this.components.map(function (component, i) {
return <{ component } key= { i } />
})}
</div>
)
}
}
How do you update the render of a react native class when it extends component?
I have tried using setState that works in the "first screen class" and in a menu/navigator class that acts as a shell of the application, but when I try to use this functions in an other class that is called from the shell I get the errormessage "Warning: getInitialState was defined on..., a plain javascript class..." and when trying to use setState or forceUpdate the message "Warning forceUpdate/setState (and so on) Can only update a mounted or mounting component.
Is there a solution to re-render by code?
import React, { Component, PropTypes } from 'react';
import { View, Text, TouchableHighlight } from 'react-native';
export default class testClass extends React.Component {
constructor(props) {
super(props)
}
getInitialState() {
return {
isLoading: true,
PackageNo: '',
PackageNoSeq: '',
hasError: false,
errorMessage: '',
};
}
render() {
return (
<View>
<Text>Test</Text>
<TouchableHighlight onPress={this.go.bind(this)}>
<Text>Go to Apple</Text>
</TouchableHighlight>
</View>
)
}
go() {
console.log("go to other");
this.props.navigator.push({ screen: 'OtherTest' });
}
}
Simple highlight . React.createClass is a traditional way to declare/create a component class in React. getInitialState is one of React.createClass life cycle method and React team just released a small syntax sugar update to allow for better use with ES6 modules by extends React.Component, which extends the Component class instead of calling createClass.
The getInitialState function is deceased, and now you need to declare all state as a simple initialisation property in the constructor
constructor(props) {
super(props);
this.state = {
isLoading: true,
PackageNo: '',
PackageNoSeq: '',
hasError: false,
errorMessage: ''
}
}
Simply use setState method to rerender. Or pass props from the parent component.
import React, { Component, PropTypes } from 'react';
import { View, Text, TouchableHighlight } from 'react-native';
export default class testClass extends Component {
state = {
text: 'Go to Apple'
}
onPress = () => {
this.setState({text: 'Go to hell'})
}
render() {
return (
<View>
<Text>Test</Text>
<TouchableHighlight onPress={this.onPress}>
<Text>{this.state.text}</Text>
</TouchableHighlight>
</View>
)
}
}