如何使用 React 中子组件的状态更新父组件?

时间:2021-02-04 14:26:28

标签: javascript reactjs modal-dialog state react-props

我有 3 个组件。

在 ListCard.js 中,我映射卡片数组,并根据用户点击的卡片,调用 handleChangeCardData 来更新模式的文本。

我的问题是:当我的 handleChangeCardData 函数在 ListCard.js 中并且我的模态在同一级别时,如何更新/更改模态的文本。 (两者都在 Board.js 中)

Board.js

const [cardTitle, setCardTitle] = useState("");
return (
     {columns.map((column, index) => (
            <div className="column__container" key={index}>
              <div className="column__header">
                <div className="columnHeader__name">
                  <p>{column.name ? column.name : "..."}</p>
                </div>
                <div className="columnHeader__button">
                  <button
                    className="btn btn-sm --create-card-btn"
                    data-bs-toggle="modal"
                    data-bs-target="#modal-card"
                    onClick={() => setColumnId(column.id)}
                  >
                    New item
                  </button>
                </div>
              </div>
              <Droppable droppableId={column.id}>
                {(provided, snapshot) => (
                  <div
                    className="column"
                    ref={provided.innerRef}
                    {...provided.droppableProps}
                  >
                    <ListCard columnId={column.id} />
                    {provided.placeholder}
                  </div>
                )}
              </Droppable>
            </div>
          ))}
    <ViewCardModal cardTitle={cardTitle} />
)

LisCard.js

const handleChangeCardData = (cardTitle) => {
    setCardTitle(cardTitle);
  }

return (
{cards.map((card, index) => (
        <>
        <div key={index}>
          <Draggable draggableId={card.id} index={index}>
            {(provided, snapshot) => (
              <div
                ref={provided.innerRef}
                {...provided.draggableProps}
                {...provided.dragHandleProps}
              >
                <div
                  className="card --listcard-card"
                  onClick={() => handleChangeCardData(card.title)}
                  data-bs-toggle="modal"
                  data-bs-target="#modal-card-details"
                  style={{ border: `2px solid ${card.color}` }}
                >
                  <div className="card-body">
                    <p>{card.title}</p>
                  </div>
                </div>
              </div>
            )}
          </Draggable>
        </div>
        </>
      ))}
)

ViewCardModal.js

function ViewCardModal(props) {
    return (
        <div>{props.cardTitle}</div>
    )
}

3 个答案:

答案 0 :(得分:1)

一般来说,lift state up。在这种情况下,这听起来意味着将状态移动到 Board 中,然后将该状态传递给任何需要它的子组件(作为 prop),并将状态设置器传递给任何(其他)需要它的子组件。< /p>

这是提升状态的最小示例。我没有尝试重新创建您示例的全部复杂性,只是提供一个 Parent 具有 ChildA 使用和 ChildB 集的状态的示例:

const {useState} = React;

const ChildA = React.memo(({counter}) => {
    console.log("ChildA rendered");
    return <div>Counter = {counter}</div>;
});

const ChildB = React.memo(({setCounter}) => {
    console.log("ChildB rendered");
    return <input
            type="button"
            value="Increment Counter"
            onClick={() => setCounter(c => c + 1)}
        />;
});

const Parent = () => {
    const [counter, setCounter] = useState(0);
    return (
        <div>
            <ChildA counter={counter} />
            <ChildB setCounter={setCounter} />
        </div>
    );
};

ReactDOM.render(<Parent />, document.getElementById("root"));
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.development.js"></script>

如果状态所在的位置和需要它的后代组件之间存在多个层次结构,您可以使用 context 代替 props(尽管您也可以查看 component composition 代替) .有关详细信息,请参阅这些链接。

答案 1 :(得分:0)

你不能直接这样做,但必须使用道具。

在列表中:

onClick={() => props.onClick(card.title)}

板内:

 handleChangeCardData = (cardTitle) => {
    setCardTitle(cardTitle);
  }

<ListCard columnId={column.id}  onClick={(e)=>handleChangeCardData(e)}/>

答案 2 :(得分:0)

ListCard 内部:

const ListCard = ({setCardTitle}) => {...}

onClick={() => setCardTitle(card.title)}

在父级中:

<ListCard columnId={column.id}  setCardTitle={setCardTitle} />