I am having a question about how to implement a callback function. In my case, I have a React app with this structure: App > Child > Button components
The problem is I do not know how to write a callback function from Button to Child
I would like to update a value in Child (e.g: inputFromButton) after clicking the button in Button Component. The handleClick() is triggered and a value will be sent to the Child component. Could someone help me to do this?
Here is my code:https://codesandbox.io/s/nifty-stonebraker-0950w8 The App component
import React from 'react';
import Child from './Child';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
data: 'Data from App'
}
}
handleCallback = (childData) => {
this.setState({ data: childData })
}
render() {
const { data } = this.state;
return (
<div>
<Child dataFromApp={data} />
</div>
)
}
}
export default App
The Child component
import React from 'react';
import { renderButton } from './Button';
class Child extends React.Component {
state = {
inputFromApp: "",
inputFromButton: ""
}
componentDidMount() {
this.setState({
inputFromApp: this.props.dataFromApp
})
}
render() {
const renderButtonItem = renderButton(this.props);
const inputFromApp = this.state.inputFromApp
const inputFromButton= this.state.inputFromButton
return (
<div>
<input value={inputFromApp}></input>
<br></br>
<input value={inputFromButton}></input>
<div>{renderButtonItem}</div>
</div>
)
}
}
export default Child
The Button component
import React from 'react';
export const renderButton = (props) => {
const handleClick = () => {
console.log('handleClick() props data from App: ' props.dataFromApp)
}
return (
<button onClick={handleClick}>Click</button>
)
}
CodePudding user response:
renderButton
is a function component and, therefore, needs to be in PascalCase:RenderButton
(although it would be better off asButton
).Move
handleClick
to theChild
component.Then in
Button
the call tohandleClick
should beprops.handleClick
sincehandleClick
will now be a property of theprops
object passed into the component. We don't need to pass down the data as a prop to the button but can, instead just log the data prop passed intoChild
.handleClick = () => { console.log(`handleClick(): ${props.dataFromApp}`); }
In
Child
, instead of callingrenderButton
, importButton
, and then use that in the render passing down the handler in the props. By doing this you're making the component as "dumb" as possible so it can be reused elsewhere in the application.<Button handleClick={this.handleClick} />