0
点赞
收藏
分享

微信扫一扫

React: 向上传递数据(child->parent 或 bottom->up 通信)

云上笔记 2022-01-08 阅读 28

可以向子组件传递数据 prop,同样可以向子组件传递 event prop 即函数 prop。
数据 prop 实现向下通信, 函数 prop 实现向上通信。

要实现向上通信,先在父组件中定义函数以及形参,然后,以函数指针的形式( 也就是不加括号,不带参数),以属性传递给子组件,由子组件提供对应实参并调用。

举例,表单提交数据,然后通过中间组件传递给App.js:
ExpenseForm -> NewExpense -> App,

// App.js
import React from "react";
import NewExpense from "./components/NewExpense/NewExpense";
import Expenses from "./components/Expenses/Expenses";

const App = () => {
  const expenses = [
    {
      id: "e4",
      title: "New Desk (Wooden)",
      amount: 450,
      date: new Date(2021, 5, 12),
    },
  ];
 //-----------------------------------------
 // 这里, 能获得第3层组件的提交的数据expense
  const addExpenseHandler=(expense) => {
    console.log('In App.js');
    console.log(expense);
  }
 //------------------------------------------
  return (
    <div>
      <NewExpense onAddExpense={addExpenseHandler} />
      <Expenses expenses={expenses} />
    </div>
  );
};
export default App;
// NewExpense.js
import React from "react";
import "./NewExpense.css";
import ExpenseForm from "./ExpenseForm";
const NewExpense = (props) => {
//----------------------------------------------
// 此函数提供给 ExpenseForm 调用,
// 实参由 ExpenseForm 提供。
  const saveExpenseDataHandler = (enteredExpenseData) => {
    const expenseData = {
      ...enteredExpenseData,
      id: Math.random().toString(),
    };
    props.onAddExpense(expenseData);
  };
//-----------------------------------------------

  return (
    <div className="new-expense">
      <ExpenseForm onSaveExpenseData={saveExpenseDataHandler} />
    </div>
  );
};
export default NewExpense;
// ExpenseForm.js
import React, { useState } from "react";
import "./ExpenseForm.css";

const ExpenseForm = (props) => {
  //   const [userInput, setUserInput] = useState({
  //     enteredTitle: "",
  //     enteredAmount: "",
  //     enteredDate: "",
  //   });
  //   const titleChangeHandler = (event) => {
  //     setUserInput({ ...userInput, enteredTitle: event.target.value });
  //   };

  //   const titleChangeHandler = (event) => {
  //       //  调用函数更新状态是安全的写法!
  //     setUserInput((prevState) => {
  //         return { ...userInput, enteredTitle: event.target.value }
  //     });
  //   };

  const [enteredTitle, setEnteredTitle] = useState("");
  const titleChangeHandler = (event) => {
    setEnteredTitle(event.target.value);
  };
  const [enteredAmount, setEnteredAmount] = useState("");
  const amountChangeHandler = (event) => {
    setEnteredAmount(event.target.value);
  };
  const [enteredDate, setEnteredDate] = useState("");
  const dateChangeHandler = (event) => {
    setEnteredDate(event.target.value);
  };

  const submitHandler = (event) => {
    event.preventDefault();
    const ExpenseData = {
      title: enteredTitle,
      amount: enteredAmount,
      date: new Date(enteredDate),
    };
    //----------------------------------
    // 调用上层函数!
    props.onSaveExpenseData(ExpenseData);
    //----------------------------------

    setEnteredTitle("");
    setEnteredAmount("");
    setEnteredDate("");
  };

  return (
    <form onSubmit={submitHandler}>
      <div className="new-expense__controls">
        <div className="new-expense__control">
          <label>Title</label>
          <input
            type="text"
            value={enteredTitle}
            onChange={titleChangeHandler}
          />
        </div>
        <div className="new-expense__control">
          <label>Amount</label>
          <input
            type="number"
            min="0.01"
            step="0.01"
            value={enteredAmount}
            onChange={amountChangeHandler}
          />
        </div>
        <div className="new-expense__control">
          <label>Date</label>
          <input
            type="date"
            min="2019-01-01"
            max="2022-12-31"
            value={enteredDate}
            onChange={dateChangeHandler}
          />
        </div>
      </div>
      <div className="new-expense__actions">
        <button type="submit">Add Expense</button>
      </div>
    </form>
  );
};
export default ExpenseForm;

与之相比较,Vue 通过 this.$emit() 方法发出事件,实现向上通信。

举报

相关推荐

0 条评论