Is it possible to create a method in Parent class in React and then pass it on to the Child and use it there.
So basically I would create a button in my Parent class, pass the function on to the Child and when the Button is clicked, the child will know about it and Parent will not really care for it?
class App extends Component {
clickMade = () => {
//This should be left empty
};
render() {
return (
<div className="App">
<Button onClick={this.clickMade}>Click me </Button>
<Child clickMade={this.clickMade} />
</div>
);
}
}
export default App;
And the Child:
class Child extends Component {
constructor(props) {
super(props);
this.handleClick = this.props.clickMade.bind(this);
}
handleClick = () => {
console.log("Click in child");
}
render() {
return null;
}
}
export default Child;
And a sandbox for this: CodeSandbox
App.js
class App extends Component {
clickMade = () => {
this.childRef.handleClick();
};
render() {
return (
<div className="App">
<Button onClick={this.clickMade}>Click me </Button>
<Child
ref={ref => {
this.childRef = ref;
}}
/>
</div>
);
}
}
Related
I am trying to call parent method from child component, but it doesn't work and method in parent element is not triggered. In this example I have only two components where ChildHello calls method in Hello component.
codesandbox
Hello.tsx
import * as React from "react";
interface Props {
itemClicked: () => void;
}
export class Hello extends React.Component<Props, {}> {
constructor(props: Props) {
super(props);
}
itemClicked = val => {
console.log(val);
};
render() {
const { name } = this.props;
return <h1 itemClicked={this.itemClicked}>{this.props.children}</h1>;
}
}
const styles = {
height: "400px"
};
export class ChildHello extends React.Component<Props, {}> {
constructor(props: Props) {
super(props);
}
render() {
return (
<div onClick={this.props.itemClicked} style={styles}>
<Hello>Hello Child</Hello>
</div>
);
}
}
You need to understand parent child relationship
in childHello you are using the click event.
<div onClick={this.props.itemClicked} style={styles}>
<Hello>Hello Child</Hello>
</div>
childhello is called by the index.jsx page
<div style={styles}>
<ChildHello name="CodeSandbox" />
</div>
Here you are not passing any click events. also, hello component is inside the child component which is wrong.
All the parent component should have click method involved and that method should be passed as props.
Like this
Parent:
<div style={styles}>
<Hello name="CodeSandbox" />
</div>
Hello component
render() {
const { name } = this.props;
return <ChildHello itemClicked={this.itemClicked} />;
}
ChildHello
render() {
return (
<div onClick={this.props.itemClicked} style={styles}>
Hello
</div>
);
}
Sandbox demo
My current structure is like this:
state={
activetab=1,
activetab2=2}
<child1 activetab={activetab}/>
<child2 activetab2={activetab2}/>
And I would like when the user changes the active tab from child 2 to update the state on the parent component, and then also handle the change on the child1 component.
child 1 code :
render() {
const activetab=this.props;
this.showimage1 = () => {
if (activetab === 1) {
return (
<img src={slide1} alt='' />
)
} else null;
}
return (
<div>
{this.showimage1()}
</div>
child 2 code :
constructor (props) {
super(props)
this.changetab= this.changetab.bind(this)
this.state={
activetab:1}
}
render () {
const activetab2=this.props;
changetab(tab) {
if (this.state.activeTab !== tab) {
this.setState({
activeTab: tab
})
}
}
return(
<div>
<button onClick={() => {
this.changetab(1)
}}
>tab1 </button>
</div>
So as you can see I want when the user changes the current tab from child 2 to pass the props in my parent component so that the child1 component knows which image to show depending on the tab. Anyone knows how to do it without rewriting everything in a single component?
Create a main component that renders the two component child 1 and 2 create only 1 source of truth means only 1 state to be pass to the child components as props.
export class MainComponent extends Component {
constructor (props) {
super(props)
this.changetab = this.changetab.bind(this)
this.state={
activetab: 0
}
}
changetab(tab) {
if (this.state.activeTab !== tab) {
this.setState({
activeTab: tab
})
}
render() {
return (
<div>
<ChildOne activetab={this.state.activetab} />
<ChildTwo activetab={this.state.activetab} changetab={this.changetab} />
</div>
)
}
}
// ChildOne Component pass state activetab as props
render() {
const { activetab } = this.props;
this.showimage1 = () => {
if (activetab === 1) {
return (
<img src={slide1} alt='' />
)
} else null;
}
return (
<div>
{this.showimage1()}
</div>
// ChildTwo Component
render () {
const { activetab, changetab } = this.props;
return(
<div>
<button onClick={() => {
this.changetab(1)
}}
>tab1 </button>
</div>
The parent component must have 2 function handlechange that you pass to your childs.
Will look something like that
// Parent
class Parent extends React.Component {
// Constructor
constructor(props) {
this.state = {
child1: 1,
child2: 0
};
}
handleChangeChild1(state) {
this.setState({ child1: state });
}
handleChangeChild2(state) {
this.setState({ child2: state });
}
render() {
return (
<div>
<Child1 onXChange={this.handleChangeChild1} />
<Child2 onYChange={this.handleChangeChild2} />
</div>
);
}
}
And in the children you do
class Child extends React.Component {
constructor(props) {
super(props)
}
handleChange(e) = () => {
this.props.onXChange
}
render() {
return (
<input onChange={this.handleChange} />
)
}
}
I recommend you read the doc
You can wrap the components in a parent component. Then you can pass a function from the parent to child 2 by attaching it to a prop. Child 2 can then call this function on a change.
In the parent:
render() {
const someFunction = (someVariable) => {
// do something
}
return(
<child2 somePropName={ this.someFunction } />
)
}
edit: removed .bind() from this example
So I have a component "itemSelection" and inside of it I map through an api response like this
<div className="row">
{this.state.items.map(i => <Item name={i.name} quantity={i.quantity} />)}
</div>
Here the state of "Item" component
constructor(props){
super(props);
this.state = {
visible: false,
selected: false,
}
}
How could I pass the state of "Item" component to "itemSelection" component?
Sending data back up to your parent component should be done by using props.
Fairly common question, see this post for the long answer.
As according to me, If I understood your question you want to call the state of the child component to the parent component.
//Child.js
import s from './Child.css';
class Child extends Component {
getAlert() {
alert('clicked');
}
render() {
return (
<h1 ref="hello">Hello</h1>
);
}
}
export default withStyles(s)(Child);
//Parent.js
class Parent extends Component {
render() {
onClick() {
this.refs.child.getAlert()
}
return (
<div>
<Child ref="child" />
<button onClick={this.onClick.bind(this)}>Click</button>
</div>
);
}
}
Also, you can get the code reference from the link: https://github.com/kriasoft/react-starter-kit/issues/909
This a little tricky but Maybe, its help you solving your problem.
//Parent.js
class Parent extends Component {
component(props) {
super(props)
this.state = {
test: 'abc'
}
}
ParentFunction = (value) => {
this.state.test = value;
this.setState(this.state);
}
render() {
return (
<div>
<Child
test={this.state.test}
ParentFunction={this.ParentFunction}
/>
</div>
);
}
}
//Child.js
import s from './Child.css';
class Child extends Component {
component(props) {
super(props)
this.state = {
test: props.test
}
}
handleChange = () => {
this.state.test = event.target.value;
this.setState(this.state);
this.handleOnSave()
}
handleOnSave = () => {
this.props.ParentFunction(this.state.test);
}
render() {
return (
<div>
<input type="text" onChange={this.handleChange} />
</div>
);
}
}
export default withStyles(s)(Child);
I am trying to change one component of a child component when another child component makes some action.
I have a parent class here:
class Parent extends Component {
constructor(){
super();
this.state={visible:true};
}
handleClick = () => {
this.setState({ visible: !this.state.visible });
};
render() {
return (
<div>
<Child1 handleClick={this.handleClick} />
<Child2 visible={this.state.visible} />
</div>
);
}
}
class Child1 extends Component {
handleClick = () => {
console.log(this.props);
this.props.handleClick();
};
render() {
return (
<div>
<button onClick={this.handleClick}>Click</button>
</div>
);
}
}
class Child2 extends Component {
render() {
return <div>//some codes</div>;
}
}
The function handleClick from the parent function works once.
Then it keeps giving me the error saying _this.props.handleClick is not a function. And there are no props from the second time.
Can anyone tell me what am I doing wrong?
I did this and it works :
render() {
return (
<div>
<Child1 handleClick={this.handleClick} />
{ this.state.visible && <Child2 />}
</div>
);
}
For reference : https://codesandbox.io/s/5zl8q7l744
Hope it helps.
I want to call child function from parent component so I found a question here
Call child method from parent
So I used this way to to called it (From 1st Answer and 2nd approach).
Now issue is how to set state in the child getAlert function
class Parent extends Component {
render() {
return (
<div>
<Child ref={instance => { this.child = instance; }} />
<button onClick={() => { this.child.getAlert(); }}>Click</button>
</div>
);
}
}
class Child extends Component {
constructor(){
super();
this.state = {message:""};
}
getAlert() {
alert('clicked');
//HERE I NEED TO SETSTATE
}
render() {
return (
{this.state.message!=""?(
<h1>{this.state.message}</h1>
):(
<h1>Hello</h1>
)}
);
}
}
In the getAlert function of child I need to setState but I couldn't able to do it. Please provide any solution
The problem seems to be that when calling setState inside the getAlert function of child, this.setState will come undefined. This happens because this inside your getAlert function doesn't refer to the context of the React Component and setState is defined for the Component. You can solve this by binding the getAlert function.
You can do it in two ways.
First: using .bind(this) in constructor
class Child extends Component {
constructor() {
super();
this.getAlert = this.getAlert.bind(this);
}
getAlert() {
alert('clicked');
//HERE I NEED TO SETSTATE
}
render() {
return (
<h1>Hello</h1>
);
}
}
Second: use Arrow function
getAlert = () => {
alert('clicked');
//HERE I NEED TO SETSTATE
}
Check this answer on Why do we need to bind React functions
Check the working snippet
class Parent extends React.Component {
render() {
return (
<div>
<Child ref={instance => { this.child = instance; }} />
<button onClick={() => { this.child.getAlert(); }}>Click</button>
</div>
);
}
}
class Child extends React.Component {
constructor(){
super();
this.state = {message:""};
}
getAlert = () => {
alert('clicked');
this.setState({message: "somemessage"});
}
render() {
return (
<div>{this.state.message!=""?(
<h1>{this.state.message}</h1>
):(
<h1>Hello</h1>
)}</div>
);
}
}
ReactDOM.render(<Parent/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"/>
class Parent extends React.Component {
render() {
return (
<div>
<Child ref={instance => { this.child = instance; }} />
<button onClick={() => { this.child.getAlert(); }}>Click</button>
</div>
);
}
}
class Child extends React.Component {
constructor(){
super()
this.state = {
message: 'google'
}
this.getAlert = this.getAlert.bind(this)
}
getAlert() {
alert('clicked');
this.setState ({
message: 'yahoo'
}, () => {
console.log(this.state.message) //the state value will be printed
});
}
render() {
console.log(this.state.message)
return (
<h1>Hello {this.state.message}</h1>
);
}
}
ReactDOM.render(
<Parent />,
document.getElementById('container')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="container"></div>
you have bind the getAlert() method to scope of the class ie). 'this'. I have added an sample code..pls check