简体   繁体   中英

Change parent state from child (where both are functional components)

The layout for the following problem looks like this:

.
├── components
│   ├── ModalPolicy.js
│   ├── Footer
│       ├── index.js
├── pages
│   ├── index.js

I've tried to render the Modal on Footer/index.js but it didn't show up (as the one we have in pages/index.js does).

Therefore, I'd like to not only render my 'antd' Modal on pages/index.js but also hold the Modal state (opened vs closed) on pages/index.js while having it's "open" method being fired from a button in Footer/index.js since that's where our Footer-ish links already live.

The hindrance is that all components involved in this problem are functional components and every solution I've found on the internet addresses cases where the parent (or both) is a (are) class-component(s). The general gist of what I'd like to accomplish is as follows:

components/Footer/index.js

// imports..

const Footer = (openModalHandler) => {
  return (
    <section id="footer">
      <Layout>
        <div className="content">
          <a href="#footer" onclick={openModalHandler}>
            Policy
          </a>
        </div>
      </Layout>
    </section>
  )
}

pages/index.js (next.js)

// imports..
import Footer from '../components/Footer'
import ModalPolicy from '../components/ModalPolicy'

const Index = () => {
   const [openPolicy, setOpenPolicy] = React.useState(false)
   const closeModalPolicy = () => { /* Called by the Modal itself, don't bother with this */
      setOpenPolicy(false)     
   }
   const openModalHandler = () => { /* Called in Footer/index.js */
      setOpenPolicy(true)
   }

   return (
      <>
        <Some />
        <Other />
        <Stuff />
        <ModalPolicy open={openPolicy} onClose={closeModalPolicy} />
        <Footer openModalHandler={openModalHandler}
      </>
   )
}

components/ModalPolicy.js

// imports..
import { Modal, Button } from 'antd'

const ModalPolicy = ({ t, open, onClose }) => {
   return (
      <Modal
        title="Política de uso y privacidad"
        visible={open}
        onCancel={onClose}
        footer={null}
        width="fit-content">
          dangerouslySetInnerHTML={{
            __html: 
              `<h1>I'd really like to use dangerouslySetInnerHTML here</h1>
               <h2>It would make things a lot easier (assuming it won't look like crap on the browser)</h2>
              `
          }}
      </Modal>
  )
}

Notes: I'm not quite sure if I really have to render the Modal on pages/index.js for it to show up correctly. Actually, I'm pretty inexperienced with React (since I'm a backend dev) and browser-side javascript in general.

If there's an easier way to accomplish this, please, let me know.

Thanks!

The issue is you forgot to destructure the properties out of the Footer component's props. Right now you are not passing the individual function through on the click handler but rather an object with the function.

aka change const Footer = (openModalHandler) to const Footer = ({openModalHandler})

const Footer = ({openModalHandler}) => {
----------------^----------------^ // curly brackets to desturcture
  return (
    <section id="footer">
      <Layout>
        <div className="content">
          <a href="#footer" onClick={openModalHandler}>
------------------------------^------ // capitalize the c (camelCase properties)
            Policy
          </a>
        </div>
      </Layout>
    </section>
  )
}

Without destructuring the param for your footer component is the props that react receives, which is an object with the key openModalHandler

Play with it live if you'd like :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM