簡體   English   中英

React:如何從父組件設置子組件中的狀態?

[英]React: How to setState in child component from parent component?

我是 React 的新手,正在嘗試設置一個 Bootstrap 模式來顯示警報消息。

在我的父 App.js 文件中,我有一個錯誤處理程序,它向 Modal.js 組件發送一個觸發模態顯示的道具,例如:

在 App.js 上:

function App() {

  const [modalShow, setModalShow] = useState(false);

  // Some other handlers

  const alertModalHandler = (modalMessage) => {
    console.log(modalMessage);
    setModalShow(true);
  }

  return (
   // Other components.
  <AlertModal modalOpen={modalShow}/>
  )
}

在 Modal.js 上:

import React, { useState } from "react";
import Modal from "react-bootstrap/Modal";
import "bootstrap/dist/css/bootstrap.min.css";

const AlertModal = (props) => {

  const [isOpen, setIsOpen] = useState(false);

  if (props.modalOpen) {
    setIsOpen(true);
  }

  return (
    <Modal show={isOpen}>
      <Modal.Header closeButton>Hi</Modal.Header>
      <Modal.Body>asdfasdf</Modal.Body>
    </Modal>
  );
};

export default AlertModal;

但是,這不起作用。 我得到錯誤:

Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.

如果我將 Modal 組件更改為“啞”組件並直接使用道具,例如:

 const AlertModal = (props) => {

  return (
    <Modal show={props.modalOpen}>
     <Modal.Header closeButton>Hi</Modal.Header>
     <Modal.Body>asdfasdf</Modal.Body>
     </Modal>
      );
    };

它確實有效,但我也想在 Modal.js 組件級別更改顯示/隱藏 state,例如在其中處理模式關閉按鈕的東西。

我不明白為什么會中斷?

這是否意味着我必須在父 App.js 級別處理模態關閉 function ?

編輯 - 完整的 app.js 內容

import React, { useState } from 'react';

import './App.css';
import 'bootstrap/dist/css/bootstrap.css';
import AddUserForm from './components/addUserForm';
import UserList from './components/userList';
import AlertModal from './components/modal';

function App() {

  const [users, setUsers] = useState([]);
  const [modalShow, setModalShow] = useState(false);


  const addPersonHandler = (nameValue, ageValue) => {
    console.log(nameValue, ageValue);
  
    setUsers(prevUsers => {
      const updatedUsers = [...prevUsers];
      updatedUsers.unshift({ name: nameValue, age: ageValue });
      return updatedUsers;
    });
  };

  const alertModalHandler = (modalMessage) => {
    console.log(modalMessage);
    setModalShow(true);
  }

  let content = (
    <p style={{ textAlign: 'center' }}>No users found. Maybe add one?</p>
  );

  if (users.length > 0) {
    content = (
      <UserList items={users} />
    );
  }

  return (
    <>
      <div className="container">
        <div className="row">
          <div className="col-md-6 offset-md-3">
            <AddUserForm onAddPerson={addPersonHandler} fireAlertModal={alertModalHandler}/>
          </div>
        </div>
        <div className="row">
          <div className="col-md-6 offset-md-3">
            {content}
          </div>
        </div>
      </div>
      <AlertModal modalOpen={modalShow}/>
    </>
  );
}

export default App;

在你的 modal.js

你應該把

if (props.modalOpen) {
    setIsOpen(true);
  }

在使用效果中。

React.useEffect(() => {if (props.modalOpen) {
    setIsOpen(true);
  }}, [props.modalOpen])

你永遠不應該像那樣調用setState 如果您這樣做,它將在每個渲染上運行並觸發另一個渲染,因為您更改了 state。 您應該將setModalShow與 if 子句一起放在useEffect中。 例如:

useState(() => {
  if (modalOpen) {
      setIsOpen(true);
    }
}, [modalOpen])

請注意,我還從props中重構了modalOpen 這樣useEffect只會在modalOpen更改時運行。

如果您已經向AlertModal組件發送了一個名為modalShow的 state ,則沒有理由使用另一個 state ,它執行相同的操作,例如isOpen

每當更改modalShow時,它都會導致AlertModal組件的重新渲染,因為您更改了它的 state,然后如果該道具為真,則在內部設置另一個 state,當您設置isOpen時會導致另一個不需要的重新渲染。 然后,在每次重新渲染時,如果 props.showModal 沒有改變(並且仍然是真的),你會一次又一次地觸發setIsOpen

如果您想控制AlertModal中的模式打開/關閉,我將執行以下操作:

<AlertModal modalOpen={modalShow} setModalOpen={setModalShow}/>

showModal state 的集合 function 傳遞給模態組件,然后根據需要使用它。 例如,在 onClick 處理程序中。

模態的.js:

import React, { useState } from "react";
import Modal from "react-bootstrap/Modal";
import "bootstrap/dist/css/bootstrap.min.css";

const AlertModal = (props) => {

  const onClickHandler = () => {
       props.setModalOpen(prevState => !prevState)
  }

  return (
    <Modal show={props.modalOpen}>
      <Modal.Header closeButton>Hi</Modal.Header>
      <Modal.Body>asdfasdf</Modal.Body>
    </Modal>
  );
};

export default AlertModal;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM