【问题标题】:How to pass values between functional components in ReactJS- output [object Object]/undefined?如何在 ReactJS 中的功能组件之间传递值 - 输出 [object Object]/undefined?
【发布时间】:2021-08-02 10:22:36
【问题描述】:

我无法在同一个 .js 文件中的功能组件中传递道具。我之前尝试过发布此问题,但没有任何帮助。

我想在我的第一个函数 GetMemID 中从 GET 请求中获取 member_id,并使用它在我的第二个函数 Transactions 中设置我的 useState 的 member_id

我知道我的 GET 请求正在运行,因为我能够在检查我的代码后看到数据。

到目前为止,使用我的代码,当我在 Transactions 中显示 member_id 时,我得到了“[object Object]”。

这是我目前的代码:

import React, { useEffect, useState } from 'react';
import { Redirect } from 'react-router-dom';
import moment from 'moment';
import  HomeNavBar from '../components/HomeNavBar.js';

var currentDate = moment().format("MM/DD/YYYY HH:mm:ss");

function GetMemID() {

  const [details, setDetails] = useState([]);  
  const [error, setError] = useState(null);

const options = {
  method: 'GET',
  headers: {
    'Content-type': 'application/json; charset=UTF-8',
    'Accept': 'application/json',
    'Authorization': `JWT ${localStorage.getItem('token')}`
  }
};

useEffect(() => {
  fetch("http://########/api/members/get/", options)
  .then(response => {
    if (response.status !== 200) {
      console.log(response.status);
      setError(response);
    }
    response.json().then(data => {
      setDetails(data);
    });
  });
}, []);

  return (
    <div className="App">
      {details.map(item => (
         <Transaction member_id={item.member_id} />
      ))}
    </div>
  );
}

function Transaction({member_id}) {
//props.state
  const [error, setError] = useState(null);
  const [trans, setTrans] = useState({member_id:member_id, category:'', description:'', amount:0}); 
  const [details, setDetails] = useState({id:0, mmeber_id:0, group:"", username:""});

  console.log("member_id: " + member_id);


//GET rerquest to get transaction memberID
  const options = {
    method: 'GET',
    headers: {
      'Content-type': 'application/json; charset=UTF-8',
      'Accept': 'application/json',
      'Authorization': `JWT ${localStorage.getItem('token')}`
    },
  };
  
  useEffect(() => {
    fetch("http://########/api/members/get/", options)
    .then(response => {
      if (response.status !== 200) {
        console.log(response.status);
        setError(response);
      }
      response.json().then(data => {
        setDetails(data);
      });
    });
  }, []);

  //POST request to API for transaction
  const optionPOST = {
    method: 'POST',
    headers: {
      'Content-type': 'application/json; charset=UTF-8',
      'Accept': 'application/json',
      'Authorization': `JWT ${localStorage.getItem('token')}`
    },
    body:JSON.stringify(trans)
  }

  const createTransaction = e => {
    e.preventDefault();

    fetch("http://########/api/transactions/post/", optionPOST)
    .then((response) => console.log('reponse: ' + response.json()))
    .then((message) => console.log('message: ' + message))
  }

  if (error) {
    return (<Redirect to="/Signin" />);
  } else{
    return (
      <div className="wrapper">
        <HomeNavBar />
        <form>
          <div className="form-horizantal">
            <fieldset>
              <div className="form-group row">
                <label className="col-md-12"><p>{currentDate}</p></label>
              </div>
              
              <div className="form-group row">
                <label className="col-md-12">
                  <p>Member ID</p>
                  <input type="text" name="member_id" defaultValue={trans.member_id} readOnly/>
                </label>
              </div>
              
              <div className="form-group row">
                <label className="col-md-12">
                  Select Category
                </label>
              </div>

              <div className="form-group row">
                <label className="col-md-12">
                  <select value={trans.category} onChange={e => setTrans({ ...trans, category: e.target.value })} >
                    <option value=""></option>
                    <option value="billsutilities">Bills/Utilities</option>
                    <option value="groceries">Groceries</option>
                    <option value="health">Health</option>
                    <option value="transportation">Transportation</option>
                    <option value="ehoppingentertainment">Shopping/Entertainment</option>
                    <option value="mics.">Mics.</option>
                  </select>
                </label>
              </div>

              <div className="form-group row">
                <label className="col-md-12">
                  <p>Description</p>
                  <input type="text" name="description" value={trans.description} onChange={e => setTrans({ ...trans, description: e.target.value })} />
                </label>
              </div>

              <div className="form-group row">
                <label className="col-md-12">
                  <p>Amount</p>
                  <input type="text" name="amount" value={trans.amount} onChange={e => setTrans({ ...trans, amount: e.target.value })} />
                </label>
              </div>
            </fieldset>

            <button type="submit" onClick={createTransaction}>Submit</button>
          </div>
        </form>
      </div>
    );
  }
}

export default Transaction;

【问题讨论】:

  • API 中的数据结构如何?
  • &lt;Transaction member_id={item.member_id} /&gt;之前记录item的值
  • console.log("member_id: " + member_id);function Transaction({member_id}) {下面的第四行在控制台中显示什么?
  • @kayuapi_my,它显示“member_id: undefined”
  • @WebbH,格式为 JSON。

标签: javascript reactjs components undefined react-functional-component


【解决方案1】:
const [isLoading,setIsLoading] = useState(false)
useEffect(() => {
  fetch("http://########/api/members/get/", options)
  .then(response => {
    if (response.status !== 200) {
      console.log(response.status);
      setError(response);
    }
    response.json().then(data => {
      setDetails(data);
      setIsLoading(true);
    });
  });
}, []);

  return (
    <div className="App">
      {isLoading && details.map(item => (
         <Transaction member_id={item.member_id} />
      ))}
    </div>

可能的解决方案是 -> 1 ) 因为我在上面的代码示例中使用了 isLoading 状态,它最初是 false 并在从 API 加载数据时设置为 true。并有条件地渲染 Transaction 组件。 2)为了更清楚地调试它,记录状态详细信息的值(以确保我们正确获取数据),类似这样 ->

useEffect(()=>{
console.log(details);
},[details])
  1. 还要检查所有来自 API 的 JSON 数据的键是否正确。

如果对您有用,请分享您的评论。干杯!

【讨论】:

    【解决方案2】:

    问题

    将传递的道具存储到本地状态是 React 中的反模式。您遇到的问题是Transaction 已安装并呈现之前 GetMemID 中的 GET 请求解析并更新 details 状态。

    解决方案 1

    只需在Transaction 组件中直接使用传递的member_id 属性即可。 trans.member_id 只使用一次并且从未更新,因此它处于状态是没有意义的。

    const [trans, setTrans] = useState({ category:'', description:'', amount:0 });
    
    ...
    
    <input type="text" name="member_id" defaultValue={member_id} readOnly/>
    

    解决方案 2

    如果您真的绝对必须member_id 存储到状态中,那么您需要使用依赖于道具值的useEffect 挂钩来更新状态。当传递的member_id 属性值更新时,效果回调将更新trans.member_id

    const [trans, setTrans] = useState({
      member_id,
      category:'',
      description:'',
      amount:0,
    });
    
    useEffect(() => {
      setTrans(trans => ({
        ...trans,
        member_id
      }));
    }, [member_id]);
    

    注意:这两种解决方案都假定您正确地获取和更新父组件中的details 状态。

    【讨论】:

      猜你喜欢
      • 2021-07-14
      • 2023-04-01
      • 2021-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-31
      • 2021-10-29
      相关资源
      最近更新 更多