React forwardRef current null in class component - reactjs

I'm relatively new to react & can't seem to figure it out, I have researched this for sometime now & nothing seems to work.
I have a parent component where I'm using createRef
class Parent extends React.Component {
constructor(props) {
super(props);
this.chartRef = React.createRef();
}
Then pass it to child & access is like following
<Grid item xs={12}>
<Child
ref={this.chartRef}
/>
<Button onClick={this.getState}> get ref info</Button>
</Grid>
But in getState chartRef current is always null
getState = () => {
console.log(this.chartRef.current);
};
Here is the child component
class Child extends React.Component {
componentDidMount() {
this.props.registerPlugins.forEach(plugin => {
Chart.pluginService.register(plugin);
});
}
render = () => {
const { data, options, plugins, height } = this.props;
const updatedOptions = {
...options
};
return <div>
<Line
height={height}
data={data}
options={updatedOptions}
plugins={plugins}/>
</div>;
};
}
Child.propTypes = {
height: PropTypes.number.isRequired,
data: PropTypes.object.isRequired,
options: PropTypes.object.isRequired,
plugins: PropTypes.array,
registerPlugins: PropTypes.array,
};
export default Child;
Any help is appreciated

You could use the callback style ref E.g.instead of passing your ref as the prop, you can pass in a reference to a function like this.handleRef
handleRef = r => {
this.chartRef.current = r;
};
<Child ref={this.handleRef} />

You can access child component in parent with help of reference as like below
import React from "react";
import { Button, View } from "react-native";
import Child from "./Child";
class App extends React.Component {
constructor() {
super();
this.chartRef = React.createRef();
}
render() {
return (
<View>
<Child ref={(r) => (this.chartRef = r)} />
<Button
title="Parent Button"
onPress={() => {
console.log(this.chartRef);
}}
></Button>
</View>
);
}
}
export default App;
// Child.js
import React from "react";
import { Button } from "react-native";
export default class Child extends React.Component {
constructor() {
super();
}
render() {
return (
<Button
title="Child Button"
onPress={() => {
alert("Child");
}}
></Button>
);
}
}
you can try this code on codesandbox example

Related

Send value to function in React-Native

I am trying to send value of TextInput to another Class Function in console.log. My approach is when the button is pressed the value FromStr in TextInput will got passed into another class function. Here's my code
import React, { Component } from "react";
import { StyleSheet, Text, View, TextInput, Button } from "react-native";
import receiveMessage from "./receiveMessage"
export default class WeatherProject extends Component{
constructor (props) {
super(props);
this.state={
From:'',
FromStr:'',
}
}
changeText=(From)=>{
this.setState({From})
}
changeText1=(To)=>{
this.setState({To})
}
onPress = ()=>{
this.setState({FromStr: this.state.From})
receiveMessage.receiveMessage();
}
render(){
return (
<View>
<View style={styles.inputFields}>
<TextInput placeholder="From" id="from" style={styles.fromField} onChangeText={this.changeText} />
<View style={styles.buttonStyle}>
<Button
title={"Go Back"}
color="#f194ff"
onPress={this.onPress}
></Button>
</View>
</View>
</View>
);
}
}
receiveMessage.js
import React, { Component } from "react";
export default class receiveMessage extends Component {
static receiveMessage=()=>{
console.log(this.state.FromStr)
}
}
React does not allow to pass the data between react components in this way.
Following is way to pass the data between components in React. To get more insights please follow
import React, { Component } from 'react';
class WeatherProject extends Component {
render() {
const messageToPassed = 'Hello';
return (
<div>
<ReceiveMessage message={messageToPassed} />
</div>
);
}
}
const ReceiveMessage = props => <h1>{props.message}</h1>;
export default App;
here we pass the value from sidemenu component by raising an event
App.js
class App extends React.Component {
handleSubmit = (e, data) => console.log(`my data from props`, data);
render() {
return (
<Sidemenu
onSubmit={(e, data)=>this.handleSubmit(e, data)} />
);
}
}
SideMenu.js
const Sidemenu = props => {
const { onSubmit} = props;
return (
<button onClick={(e, type)=>this.onSubmit(e, 'mydata')} />
);
}

React child component unmounting when parent component state is updated

I am seeing strange behavior that I don't understand in the following code
export class PlayerListPage extends React.Component<PlayerListPageProps, {toggle: boolean}> {
constructor(props: PlayerListPageProps) {
super(props);
this.state = {
toggle: false
};
}
handleToggle = () => {
this.setState({
toggle: !this.state.toggle
})
}
render() {
return (
<div>
<TextField
key={1}
label={'label'}
value={'value'}
/>
<Button
onClick={this.handleToggle}
>
Click
</Button>
</div>
)
}
}
Every time this toggle method is triggered, and updates the component's state, the TextField component is unmounted/remounted instead of just re-rendering.
I would expect TextField to re-render without unmounting first. Could somebody kindly point out what I am doing wrong?
Some additional context: here is the parent component (which is the root of the app):
#observer
export class RootView extends React.PureComponent {
private rootStore: RootStore = new RootStore();
private appTheme : any = createMuiTheme(DarkTheme);
#observable private player: Player
async componentDidMount() {
await this.rootStore.playerStore.retrievePlayerBios();
this.player = this.rootStore.playerStore.getPlayer('12');
}
render() {
console.log(this.appTheme);
return (
<main>
<MuiThemeProvider theme={this.appTheme}>
<Provider rootStore={this.rootStore}>
{/* {!!this.player && <PlayerStatsView player={this.player}/>} */}
<PlayerListPage/>
</Provider>
</MuiThemeProvider>
</main>
)
}
}

ReactJs TypeError default.a.render is not a function

I am trying to use Auth0EditProfileWidget
getting error at line 65:
this.form = React.render( <FormControl data={data} onSubmit={onSubmit} />, container );
TypeError: react__WEBPACK_IMPORTED_MODULE_0___default.a.render is not
a function
can anybody help me?
Edited: code
import React from 'react';
import formSerialize from 'form-serialize';
import FieldTypeMapper from './FieldTypes/FieldTypeMapper'
class FormFieldList extends React.Component {
render() {
var fieldNodes = this.props.data.map( data => FieldTypeMapper(data.type)(data) );
return ( <div>{fieldNodes}</div> );
}
}
class ErrorItem extends React.Component {
render() {
return ( <li>{this.props.message}</li> );
}
}
class ErrorControl extends React.Component {
render() {
var errors = this.props.data.map( error => ( <ErrorItem key={error} message={error} /> ) );
var style = {};
if (errors.length === 0) {
style.display = 'none';
}
return ( <ul className="error" style={style}>{errors}</ul> );
}
}
class FormControl extends React.Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
this.state = props.data;
}
render() {
return (
<form onSubmit={this.handleSubmit} ref="editProfileForm">
<ErrorControl data={this.state.errors} />
<FormFieldList data={this.state.fields} />
<input type="submit" value="Save" />
</form>
);
}
handleSubmit(e) {
e.preventDefault();
var form = this.refs.editProfileForm.getDOMNode();
var data = formSerialize(form, {hash: true});
this.props.onSubmit(data);
}
}
export default class EditProfileForm {
constructor(container, data, onSubmit) {
this.form = React.render( <FormControl data={data} onSubmit={onSubmit} />, container );
}
render(data) {
this.form.setState(data);
}
}
Can you try changing your EditProfileForm class to this:
export default class EditProfileForm {
constructor(props) {
super(props)
}
render() {
return(<FormControl data={this.props.data} onSubmit={this.props.onSubmit} />)
}
}
And then call ReactDom.render() like this:
ReactDOM.render(<EditProfileForm data={dataProp} onSubmit={onSubmitProp} />, container);
export default class EditProfileForm {
constructor(container, data, onSubmit) {
this.form = React.render( <FormControl data={data} onSubmit={onSubmit} />, container );
}
render(data) {
this.form.setState(data);
}
}
things to note here, first, is EditProfileForm a react component or not because EditProfileForm do not extends React.Component
and Second thing is that this.form.setState(data); what is the value of setState why you use this.form.setState() what is it doing.

React native props to parent component

To start i am sorry i am a new on native react
I have a project with react navigation who show this component.
import React, { Component } from 'react';
import {FlatList,StyleSheet,View,TouchableHighlight,Text} from 'react-native'
import {
Container,
Button,
ListItem,
Left,
Right,
Icon,
Body
} from 'native-base';
import Customer from '../Customer';
import Search from '../../../components/Search'
export default class SearchCustomer extends Component {
constructor(props) {
super(props);
this.state = {
customerList:[]
}
}
render() {
return (
<Customer>
<Search
setCustomerList = {(customerList) => {this.setState({customerList})}}
/>
<FlatList
data={this.state.customerList}
keyExtractor={item => item.id}
renderItem={({ item, index}) => (
<ListItem onPress={(item) => this.props.callback()}>
<Left style={styles.left}>
<Text>{item.firstname} {item.lastname}</Text>
<Text style={styles.subtitle}>{item.email}</Text>
</Left>
<Right>
<Icon name='arrow-forward' />
</Right>
</ListItem>
)}/>
</Customer>
)
}
}
This component call his parent that here below
import React, { Component } from 'react';
import {
Container,
Button,
Text,
} from 'native-base';
import Order from '../Order';
export default class Customer extends Component {
constructor(props) {
super(props);
this.state = {
}
}
render() {
return (
<Order>
{this.props.children}
</Order>
)
}
}
I want to know how can i send data from the child to his parent with this configuration.
Currently i am trying to catch this.props.callback() in the parent but i can't use this callback={() => {console.log('Ok')}}
I have this error
Someone have a solution ?
Using some of your class you can define a method in your parent class then pass the function as props to child
export default class Customer extends Component {
constructor(props) {
super(props);
this.state = {
}
}
callback = (data) => { console.log(data) }
render() {
return (
<Order callback={this.callback}>
{this.props.children}
</Order>
)
}
}
Then from child you can provide the data in the callback for parent.
export default class Order extends Component {
constructor(props) {
super(props);
this.state = {
}
}
render() {
return (
<TouchableOpacity onPress={() => this.props.callback('hi')}>
<Text>Click Me!</Text>
</TouchableOpacity >
)
}
}
read this for more good understanding : https://reactjs.org/tutorial/tutorial.html#passing-data-through-props

Using childrens in React Container

Can I use children in React Container or is it wrong?
For example, I have a list of buttons(ActionButton) that are grouped together (ActionMenu).
import React from 'react';
class App extends React.Component {
render() {
return (
<ActionMenu>
<ActionButton name="New" icon="add" />
<ActionButton name="Delete" icon="remove" />
</ActionMenu>
)
}
}
class ActionMenu extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
alert('Click!');
}
render() {
return React.Children.map(this.props.children, (button) =>
React.cloneElement(button, {
onClick: this.handleClick
})
);
}
}
function ActionButton({ name, icon, onClick }) {
return <button class={icon} onClick={onClick}>{name}</button>
}
You can use children regardless of whether it's a component of container.
"[children are] especially common for components like Sidebar or Dialog that represent generic 'boxes'."
In your case you have a menu, which falls into this category.
https://reactjs.org/docs/composition-vs-inheritance.html
I think this is what you are after. Actually you should just put the children in its closest parent instead of its grandpa.
import React from 'react';
import { render } from 'react-dom';
function ActionButton({ name, handleClick }) {
return <button onClick={handleClick}>{name}</button>
}
class ActionMenu extends React.Component {
constructor(props) {
super(props);
}
handleClick = () => {
alert('Click!');
}
render() {
return (
<div>
<ActionButton name="add" handleClick={this.handleClick}/>
<ActionButton name="remove" handleClick={this.handleClick} />
</div>
);
}
}
class App extends React.Component {
render() {
return (
<ActionMenu />
)
}
}
render(<App />, document.getElementById('root'));
You can try to run it in sandbox.
By the way, using bind is quite redundant now, we can use public class fields syntax, which is already ECMA stage 2.

Resources