I have a parent component
class ParentComponent extends React.PureComponent {
render(){
return(
//IN HERE I'm calling child parent
<ChildComponent/>
)
}
}
class ChildComponent extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
sample: '',
};
}
how can I get the sample state to the parent component?
So at the Parent Component make a method which receives value in return.
StateValue = (value) =>{
console.log(value);
}
Pass this method as props to the child component.
<ChildComponent method={this.StateValue}/>
At the child component Pass the state value to the method props received in step 2.
constructor(props) {
super(props);
this.state = {
sample: 'hi',
};
}
render(){
this.props.method(this.state.sample)
return(
<></>
)
You will get your state value in StateValue Method from the props in your parent component.
Try this:
class ParentComponent extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
sample: '',
};
}
render(){
return(
<ChildComponent sample={this.state.sample} setState={(sample) => this.setState({ sample })} />
)
}
}
class ChildComponent extends React.PureComponent {
// you can now call this.props.setState(value); to set parent component state.
// and access the sample state: this.props.sample;
}
One option is to specify a callback as a prop. Like this:
class ParentComponent extends React.PureComponent {
onSample = (sample) => {
// handle sample
}
render(){
return(
//IN HERE I'm calling child parent
<ChildComponent
callback={this.onSample}
/>
)
}
}
class ChildComponent extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
sample: '',
};
this.onSample = props.callback
// call later on via this.onSample(<sample>);
}
Related
How do I get access from component to the methods of the owner of this component?
I.e. (maybe) you need to get a pointer to the owner of the element and already call the method by the pointer.
For example:
component #1
class MyReport extends Component {
my_method() {}
render() {
return (
<MyReport>
<MyElement />
</MyReport>
);
}
}
and component #2
class MyElement extends Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick(event) {
// GET METHOD my_method OF OWNER
console.log(parent.my_method());
}
render() {
return <Button onClick={this.handleClick}>Press</Button>;
}
}
If you are looking how to call a method of the parent you just pass it trough props of the child component:
Component #1
class MyReport extends Component {
my_method() {
}
render() {
return (
<MyReport>
<MyElement methodFromParent={this.my_method}/>
</MyReport>
);
}
}
Component #2
class MyElement extends Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick(event) {
// GET METHOD my_method OF OWNER
console.log(this.props.methodFromParent);
}
render() {
return (
<Button onClick={this.handleClick}>Press</Button>
);
}
}
Although, you wrapping MyElement with MyReport seems like a mistake you made when writing this question.
Hi I would like to pass data from same child to parent component multiple times.
class ChildComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
stateVariabes:null
};
// callback from parent
this.props.onSelect(this.state);
}
handleChange(event) {
const value = event.target.value;
this.setState(
{
stateVariabes: value
},
function() {
console.log(this.state);
// callback from parent
this.props.onSelect(this.state);
}
);
}
}
class ParentComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
childOne: null,
childList: [],
childOther: null
};
}
childCallbackFunction = childData => {
// which child state shall I set here
this.setState({ weekDay: childData });
};
render() {
return (
<div className="App">
<ChildComponent onSelect={this.childCallbackFunction} />
<ChildComponent onSelect={this.childCallbackFunction} />
<ChildComponent onSelect={this.childCallbackFunction} />
<ChildComponent onSelect={this.childCallbackFunction} />
</div>
);
}
}
When I use only of one the ChildComponent the update of state from child to parent works as expected but when I have multiple ChildComponent inside render of Parent the state update does not happen.
Can someone suggest whats the right way to achieve the task?
When using Class components, you need to bind your methods. From React documentation:
In JavaScript, class methods are not bound by default. If you forget to bind this.handleClick and pass it to onClick, this will be undefined when the function is actually called.
So, in your case, your ChildComponent should have a
this.handleChange = this.handleChange.bind(this);
You should also remove this from your constructor, since it is calling your callback on initialization:
// callback from parent
this.props.onSelect(this.state);
Here is a working example: https://codesandbox.io/s/intelligent-night-xlhzj
More information in this link.
This is how it should do it.
child=>
class ChildCom extends Component {
constructor(props) {
super(props);
this.state = {
stateVariabes: null
};
}
componentDidMount() {
this.onSelect()
}
onSelect = () => {
const value = 'some value coming from your event';
this.props.trigger(value);
};
Parent=>
class ParentCom extends Component {
constructor(props) {
super(props);
this.state = {
childOne: null,
childList: [],
childOther: null,
};
}
childCallbackFunction = childData => {
// you can do anything with your child component values here
console.log('child value: ', childData)
};
render() {
return (
<div className='App'>
<ChildCom trigger={this.childCallbackFunction} />
<ChildCom trigger={this.childCallbackFunction} />
<ChildCom trigger={this.childCallbackFunction} />
<ChildCom trigger={this.childCallbackFunction} />
</div>
I'm new to the world of React and I'm trying to build a parent component with a function that should be invoked from a child component. However, when I call the function, I get the error message in the title. I have something similar:
class ParentComponent extends React.Component {
constructor(props) {
super(props);
this.myFunction = this.myFunction.bind(this);
}
myFunction(param) {
//do something
}
render(){
return(
<ChildComponent event={this.myFunction} />
);
}
}
class ChildComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
inheritedFunction: this.props.event
};
}
childFunction(param) {
//do a few things first
this.state.inheritedFunction(param);
}
render(){
return(
<input type="checkbox" onChange={this.childFunction.bind(this)></input>
);
}
}
My code compiles and runs, and then when it gets to execute the childFunction( ) upon selecting the checkbox, this.state.inheritedFunction(param) says that it is not a function and the application collapses. I suspect that it has to do something with binding, but I'm really not sure and stuck with this problem.
I'm new to React, so please be nice. :-) Anyone knows what I messed up?
class ParentComponent extends React.Component {
constructor(props) {
super(props);
this.myFunction = this.myFunction.bind(this);
}
myFunction = (param) => {
//do something
alert(param);
}
render(){
return(
<ChildComponent event={this.myFunction} />
);
}
}
class ChildComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
inheritedFunction: this.props.event
};
}
childFunction(param) {
//do a few things first
this.props.event(param);
}
render(){
return(
<input type="checkbox" onChange={this.childFunction.bind(this)></input>
);
}
}
I think your problem is trying to save a reference inside the state and then on the onchange callback you are binding again the function.
remove the state on the constructor and just call it directly from props
class ParentComponent extends React.Component {
constructor(props) {
super(props);
this.myFunction = this.myFunction.bind(this);
}
myFunction(param) {
//do something
}
render(){
return(
<ChildComponent event={this.myFunction} />
);
}
}
class ChildComponent extends React.Component {
constructor(props) {
super(props);
this.childFunction = this.childFunction.bind(this); // bind on the constructor.
}
childFunction() {
//do a few things first
this.props.event(this) //call the prop directly here.
}
render(){
return(
<input type="checkbox" onChange={this.childFunction></input> // no more binding here
);
}
}
class ParentComponent extends React.Component {
constructor(props) {
super(props);
}
myFunction = param => {
//do something
};
render() {
return <ChildComponent event={this.myFunction} />;
}
}
class ChildComponent extends React.Component {
constructor(props) {
super(props);
}
childFunction = (param) => {
//do a few things first
this.props.event(param);
}
render() {
return <input type="checkbox" onChange={this.childFunction} />
}
}
I want to update the value of 'change_color' in the second class and automatically render it in the first class when the value gets changed.
Assume, 'Second' component as the child of the 'First' component.
Solved it. Code is edited and it is the answer.
class First extends Component {
constructor() {
super();
this.state = {
change_color: false
}
this.handleChange = this.handleChange.bind(this);
}
handleChange() {
this.setState({
change_color: true
})
}
render() {
console.log(this.state.change_color);
return(<div><Second colorChange={this.handleChange} /></div>)
}
}
class Second extends Component {
constructor() {
super();
}
render() {
return(<div><button onClick={this.props.colorChange} /></div>)
}
}
Maybe you can try this, just make a container component, and set the value you want to change into a state of the container component, add a method to change the state value, then, you can use "this.props.handleColorChange" to call the method of the parent component in children components.
class ParentComponent extends Component {
constructor() {
super();
this.state = {
change_color: false
}
}
handleColorChange= () => {
const {change_color} = this.state;
this.setState = {
change_color: !change_color
}
}
render() {
const {change_color} = this.state,
{handleColorChange} = this;
return (
<div>
<ChildComponent1
color={change_color}
handleColorChange={handleColorChange}
/>
<ChildComponent2
color={change_color}
handleColorChange={handleColorChange}
/>
</div>
);
}
}
class ChildComponent1 extends Component {
constructor() {
super();
}
render() {
const {color} = this.props;
return(
<span>now, the color is {color}</span>
)
}
}
class ChildComponent2 extends Component {
constructor() {
super();
}
const {handleColorChange} = this.props;
return(
<button onClick={handleColorChange}>click to change color</button>
)
}
What you need to do is lifting up the state. Create a new component that has a state with the colour and the change colour function. Then pass to first and second componentes the corresponding properties as props and inside of them call the function to change the colour. Does it makes sense?
So I have one root component and two child components. I have trying to get one child to call a method that is up in in the root component and update the state up in the root component, and pass the updated down to the other component, but I am getting the following error.
What could be the issue?
warning.js?8a56:36 Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the firstChild component.
Here is the code:
firstChild.js
export default class firstChild extends React.Component {
constructor(props) {
super(props);
this.state = {
nameText: '',
}
}
nameChange(event) {
this.setState({
nameText: event.target.value,
})
}
submitClick() {
var nameText = this.state.nameText;
this.props.saveName(nameText)
this.setState({nameText: ''});
}
render() {
var st = this.state;
var pr = this.props;
return (
<input
placeholder='Enter Name'
onChange={this.nameChange.bind(this)}
value={this.state.nameText}
/>
<button
onClick={this.submitClick.bind(this)}
/>
And in root component, App.js:
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
submitSuccess: false
}
}
saveName(nameText) {
this.setState({submitSuccess: true});
}
render() {
var props = {};
props.submitSuccess = this.state.submitSuccess;
return (
<div>
<firstChild
saveName={this.saveName.bind(this)}
/>
{React.Children.map(this.props.children, function(child) {
return React.cloneElement(child, props);
})}
</div>
)
}
}
And my secondChild.js:
export default class secondChild extends React.Component {
static propTypes = {
submitSuccess: React.PropTypes.bool.isRequired,
}
constructor(props) {
super(props);
this.state = {
}
}
render() {
return (
<div>
{this.props.submitSuccess}
</div>
)
}
}
Fisrt, rename all your React components as Camel Case like this.
class firstChild ... --> class FristChild
<fristChild> --> <FristChild>
Second, in your FirstChild render method, you should wrap your elements into an enclosing tag like this:
class FirstChild extends Component {
render(){
return (
<div>
<input ... />
<button ... />
</div>
)
}
}
Third, when you use cloneElement upon this.props.children, you should use Proptypes.<type> in your secondChildren instead of Propstypes.<type>.isRequired. Check it here to see why.
class SecondChild extends Component {
static propTypes = {
submitSuccess: React.PropTypes.bool, // remove isRequired
}
}
Regardless all above, I have tested your code and it works fine.
You can try and use componentWillUnmount lifecycle function in order to check when the component is unmounted.
You can also use a flag to signal that the component is unmounted before setting the state:
saveName(nameText) {
if (!this.isUnmounted){
this.setState({submitSuccess: true});
}
}
componentWillUnmount() {
this.isUnmounted = true;
}