skip to Main Content

I saw a few similar questions, but about parent/child elements, i have that kind of node tree:

IndexPage -> Modals -> ClientDetails(it's modal component)
          -> Header

I want to call ClientDetails.openModal inside Header, tried many ways like creating refs for ClientDetails in indexPage and then pass indexPage to header like prop, but it’s works strange, i see refs of props.IndexPage, but when trying access refs directly it’s underfind

enter image description here
enter image description here

class IndexPage extends React.Component {
  constructor(props) {
    super(props);

    this.modals = React.createRef();
  }

  render() {
    return (
      <Layout>
        <SEO/>
        <Header indexPage={this}/>
        <Story/>
        <Products/>
        <Clients/>
        <Reviews/>
        <Partners/>
        <Footer/>
        <Modals ref={this.modals} />
      </Layout>
    )
  }
}
class Modals extends React.Component {
  constructor(props) {
    super(props);
    this.clientDetailsRef = React.createRef();
  }

  render() {
    return (
      <>
        <ThankYou/>
        <ContactDetails ref={this.clientDetailsRef}/>
      </>
    )
  }
}
class Header extends React.Component {
  constructor(props) {
    super(props);
    this.state = { isActive: false, isSticky: false };
    this.toggle = this.toggle.bind(this);


    this.indexPage = props.indexPage
    console.log(this.indexPage)
    console.log(this.indexPage.modals)
  }
}

3

Answers


  1. I would try doing this:

    class IndexPage extends React.Component {
      constructor(props) {
        super(props);
    
        this.state = {modalsRef: null};
      }
    
      render() {
        return (
          <Layout>
            <SEO/>
            <Header modalsRef={this.state.modalsRef}/>
            <Story/>
            <Products/>
            <Clients/>
            <Reviews/>
            <Partners/>
            <Footer/>
            <Modals ref={r => !this.state.modalsRef && this.setState({modalsRef:r})} />
          </Layout>
        )
      }
    }
    

    But please note: the property won’t work in the constructor of Header most likely. It should work though by the time you’re doing things like Button.onClick callbacks.

    Login or Signup to reply.
  2. Here is a small fiddle for calling a child function from the parent

    https://jsfiddle.net/c1qfn9Lx/9/

    class Modal extends React.Component {
     constructor(props) {
      super(props);
      this.state= {
       showModal: false
      }
      this.toggleModal = this.toggleModal.bind(this)
     }
     toggleModal() {this.setState({showModal: !this.state.showModal})}
    
    render() {
     const { showModal } = this.state;
     return(
      <div className="modal">
       {showModal && 
        <div>
         Showing modal
        </div>
       }
      </div>
     )
     }
    }
    
    class TodoApp extends React.Component {
     constructor(props) {
       super(props)
       this.modalRef = React.createRef()
       this.handleClick = this.handleClick.bind(this);
     }
    
     handleClick() {
      this.modalRef.current.toggleModal();
     }
    
     render() {
       return (
         <div className="parent">
           <Modal ref={this.modalRef} />
           <button onClick={this.handleClick}>Click</button>
         </div>
       )
     }
    }
    
    ReactDOM.render(<TodoApp />, document.querySelector("#app"))
    
    
    Login or Signup to reply.
  3. I think you can solve your problem using react.js context.
    You wanted to control the Modals component in the Header component. So you tried to reference the Modals component toggle function in the Header component to solve the problem.
    I think it is a fine solution.
    But in my opinion, sharing state in peer components is also another solution.
    So you can use react.js context to share states between two peer components in a parent component of them. I think doing this is following react declarative programming.

    Please check this code

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search