ReactJS - Call parent method from child component and await response from parent - reactjs

I just started working with ReactJS so I am still getting the hang of it. I need some help with one aspect to which I found no answer. I am trying to call a function in a parent component from a child component, but I also want to receive an answer from the parent, containing some data. How can I achieve that?
Currently what I am doing is:
import Parent from './parent.js';
class Child extends React.Component {
constructor(props) {
super(props);
};
click = () => {
this.props.parentMethod();
}
render() {
<div onClick={this.click}>Hello Child</div>
}
}
class Parent extends React.Component {
constructor(props) {
super(props);
};
someMethod() {
console.log('bar');
}
render() {
<Child parentMethod={this.someMethod}>Hello Parent, {this.props.children}</Child>
}
}

You wouldn't normally do this. Data flows from parent ยป child in React. Thus, if executing a function on Parent changes data passed to Child, your Child component would re-render.
Using your example:
class Child extends React.Component {
render() {
<div onClick={this.props.changeName}>
Hello, {this.props.displayName}
</div>
}
}
class Parent extends React.Component {
constructor(){
this.state = {
name: "Bob",
}
}
changeName = () => {
this.setState({ name: "Sally" })
}
render() {
return(
<Child
changeName={this.changeName}
displayName={this.state.name}
/>
)
}
}
In this, clicking on the div inside Child would change the name property of Parent's state, which would then be passed to Child and get re-rendered.

You can keep the data on your parent component's state and pass it to children. After calling your function this data changes in the parent, then goes back to child again. By the way, you are missing returns in your render methods. Look for it.
const Child = ( props ) => {
const click = () => {
props.parentMethod();
}
return (
<div onClick={click}>
Hello, this is Child.
Data is now: {!props.data ? "No data yet!" : props.data }
</div>
);
}
class Parent extends React.Component {
state = {
data: "",
}
someMethod = () =>
this.setState({ data: "bar"});
render() {
return (
<Child data={this.state.data} parentMethod={this.someMethod} />
);
}
}
ReactDOM.render(<Parent />, document.getElementById("root"));
<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="root"></div>

Related

I don't understand why clicking the button would invoke getDerivedStateFromProps in child component twice

I am new to React. I got confused about getDerivedStateFromProps method in the child component. When I clicked the button, the Child derived message showed up twice. I think it should only show up one time.
`
class Parent extends Component {
constructor(props) {
super(props);
this.state = {
count: 0
}
}
changeState = () => {
this.setState((prev) => ({count: prev.count + 1}))
}
render() {
return (
<div>
<Child data={this.state.count}> </Child>
<button onClick={this.changeState}>
click me
</button>
</div>
);
}
}
Parent.propTypes = {};
export default Parent;
`
class Child extends Component {
constructor(props) {
super(props);
this.state = {count: -1}
}
static getDerivedStateFromProps(props, state) {
// console.log(state)
// console.log(props)
console.log("child Derived")
return {count: props.data}
}
render() {
return (
<div>
count {this.state.count}
</div>
);
}
}
Child.propTypes = {};
export default Child;
I found the bug. I am not sure if it's a bug or not. In index.js file that was automatically created by the command 'create-react-app', it has <React.StrictMode> that is around <App />. After removing it, the child derived message only shows up once.

How to access component with ref when it wrapped by withRouter in NextJS?

I have a React component that I exported it like this:
class Child extends Component {
getStatus() {
return 'I am child!';
}
render() {
return (<div>Child</div>);
}
}
export default withRouter(Child)
And I have another class that needs the ref of "Child" component like this:
class Parent extends Component {
constructor(props) {
super(props);
this.childRef = createRef();
}
handleLogChildStatus = () => {
if (typeof this.childRef.current.getStatus === 'function') {
console.log(this.childRef.current.getStatus());
} else {
console.log(' Can not access to child component via ref! ');
}
}
render() {
return (
<div>
<Child ref={this.childRef} />
<div onClick={this.handleLogChildStatus}>Log child status</div>
</div>
);
}
}
This sample shows me I can not access to child component ref because it wrapped by withRouter HOC.
My question is How I can access to child ref component when it wrapped by nextjs withRouter>
I think one of below should work
export default withRouter(Child, { withRef: true })
2nd option
this.childComponent = React.createRef();
....
<Child wrappedComponentRef={c => (this.childComponent = c)} />

Pass event through nested components bottom to top

While this question has been asked before I did not find an answer. I have components nested to the level of great grandchild and I don't know how to get the data from the bottom to the top.
<Parent/>
<Child/>
<GrandChild/>
<GreatGrandChild/>
See an example: fiddle
The great grandchild is a form and I want the input data to get to the parent at the top. I had it working when it was just nested one level deep, but now that it is deeply nested it does not work. I'm not sure how to even pass the event up two levels.
I've heard using redux is possible but I wonder if there is a way to avoid it. Or, how do I avoid the nesting? Even through they are all actually separate components should I just move them into one big component? This might work but seems like bad practice?
Very simplified, you could just pass the function through all the components:
class GreatGrandChild extends React.Component {
render() {
return (
<div>
<input onChange={this.props.onChange}/>
<h2>I'm the GreatGrandChild</h2>
</div>
)
}
}
class GrandChild extends React.Component {
render() {
return (
<div>
<h2>I'm the GrandChild</h2>
<GreatGrandChild onChange={this.props.onChange}/>
</div>
)
}
}
class Child extends React.Component {
render() {
return (
<div>
<GrandChild onChange={this.props.onChange}/>
<h2>I'm the child</h2>
</div>
)
}
}
class Top extends React.Component {
constructor(props) {
super(props)
this.state = {
}
}
handleChildchange = (e) => {
console.log('child event on parent')
console.log(e.target.value);
}
render() {
return (
<div>
<Child onChange={this.handleChildchange}/>
<h2>I'm the parent</h2>
</div>
)
}
}
ReactDOM.render(<Top />, document.querySelector("#app"))
Redux is overkill for simple passing of props. You can pass props down through each child but it's easier to use the Context API like so:
Parent Component:
const MyContext = React.createContext('default');
export MyContext;
class Parent extends React.Component {
myFunction() {
//Do something here
}
render() {
return (
<MyContext.Provider value={this.myFunction}>
<ChildComponent />
</MyContext.Provider>
);
}
}
export default Parent;
Child Component:
import { MyContext } from './Parent';
class ChildComponent extends React.Component {
render() {
const { myFunction } = this.context;
return (
<div onClick={myFunction}>Click Me!</div>
);
}
}
ChildComponent.contextType = MyContext;
You can use the context as deep as you'd like, as long as you import it.
Simply pass a callback down from the parent via the props and make Sure it's passed all the way down to where you need it.
You also can pass props to your each child component in nesting and whenever values changed, you can call a parent function (nested) to get latest values in parent.

React: How can you access the class name of a parent component from a child without passing it down as props?

Say you have a parent component:
// ParentComponent
class ParentComponent extends React.Component {
render() {
return(
<ChildComponent/>
)
}
}
From inside the child component, is there a way to access the class name of the parent component without passing this down as props?
// ChildComponent
class ChildComponent extends React.Component {
// ?????
getParentComponentName() {
return this.??? // Should return "ParentComponent"
}
render() {
return(
<div/>
)
}
}
I'd prefer to be able to access this without passing it down as props. Thank you!
You need to access ReactInternalFiber like
class Child extends React.Component {
constructor(props) {
super(props);
this.state = { name: '' }
}
getParentName = () =>{
this.setState({ name: this._reactInternalFiber._debugOwner.type.name })
}
render() {
return (
<div>
<h1>Name: {this.state.name}</h1>
<button onClick={this.getParentName}>Get Parent Name</button>
</div>
)
}
}

Children to children components communication

I have 1 parent component name [Parent-1] and 1 child component name [Child-1]. Now, I have few more other components name [Other-1] and [Other-2].
Now i am passing [Other-1] and [Other-2] component to [Child-1] component. JSX is rendering correct. How can i access [Other-1/2] component functions from [Child-1] ? or How can i pass props to [Child-1] from [Other-1/2] ?
By using refs I am able to call the [Other-1/2] functions from [Parent-1] but I want to access from [Child-1]. I tried passing refs to [Child-1] like <Child abc={() => this.refs.other1.hello()}/> or <Child abc={this.refs.other1.hello()}/> but this is not working.
By using global Event Emitter way I am able to achieve solution to my above problem. But not sure if that's the appropriate way in React.js
I think you're not using the refs properly.
When you try to give an arrow function to refs it will sometime causes error due to the ref returning null. See my question to find out why.
The example should help you understand refs
Hope this helps!
class Others1 extends React.Component {
log(){
console.log('Hello from Others1')
}
render() {
return <h1>Others1</h1>
}
}
class Others2 extends React.Component {
log(){
console.log('Hello from Others2')
}
render() {
return <h1>Others2</h1>
}
}
class Child extends React.Component{
other1Ref(el) {
el.log()
}
other2Ref(el) {
el.log()
}
render() {
const Others1 = this.props.others1
const Others2 = this.props.others2
return (
<div>
<Others1 ref={this.other1Ref}/>
<Others2 ref={this.other2Ref}/>
</div>
)
}
}
class Parent extends React.Component{
render() {
return <Child others1={Others1} others2={Others2}/>
}
}
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"></div>
Additionally, There can be a case where we have to pass [Others1] and [Others2] as array of object say E.g.
class Others1 extends React.Component {
log(){
console.log('Hello from Others1');
}
render() {
return <h1>Others1</h1>
}
}
class Child extends React.Component{
other1Ref(el) {
el.log();
}
render() {
// 'i' need to be counter for eg. 0, 1, 2 ...
const Others1 = this.props._array[i].type();
Other1.other1Ref();
return (
<div></div>
)
}
}
let _array = [<Others1/>, ...];
class Parent extends React.Component{
render() {
return <Child _array={_array} />
}
}
ReactDOM.render(<Parent/>, document.getElementById('app'))
By using .type() we will able to access Children function in case of array of objects/components

Resources