如何从使用状态挂钩的功能性父组件传递道具?

Posted

技术标签:

【中文标题】如何从使用状态挂钩的功能性父组件传递道具?【英文标题】:How can I pass props from a functional parent component that uses the state hook? 【发布时间】:2021-09-03 02:45:14 【问题描述】:

所以我正在开发这个 UserData 应用程序(用于练习目的)。我有一个组件用于存储硬编码的用户数据——一个包含不同用户对象的数组。在我的应用程序中,我希望屏幕左侧有一个用户列表(仅显示用户名),右侧有一个面板,显示我在列表中选择的用户的所有详细信息。 (查看屏幕截图。) 我将数据导入到我的功能性父组件 AppContainer.js,我在其中使用状态挂钩将选定的用户 ID 存储在 state = 'selectedUserId' 中。我在第一次渲染时给它一个 null 值,以便在我点击任何人之前它会说“选择用户”。在我的 handleClick 函数中,我想在每次点击等时更新 userId。在我的 App.js 组件中,我想映射数据并使用不同的 li 元素以及面板呈现 ul。在此过程中,我犯了一个错误——当我点击一个用户时,会抛出一个类型错误并且控制台说“handleClick 不是一个函数”。任何想法为什么?如果您有兴趣,这里是我的沙盒列表:https://codesandbox.io/s/user-data-app-with-prop-types-tkphx?file=/src/AppContainer.js:0-571

这是 UserData.js :

export const USERS_DATA = [
id: 1,
user_name: "jwrefford0",
first_name: "Jozef",
last_name: "Wrefford",
occupation: "Editor",
catch_phrase: "repurpose next-generation schemas"
  ]

这是 AppContainer.js:

import React from 'react';
import ReactDOM from 'react-dom';
import  App  from './App';
import  useState  from "react";
import  USERS_DATA  from "./UserData";

export default function AppContainer() 
  const [selectedUserId, setSelectedUserId] = useState(null);

  const handleClick = (newUserId) => 
  setSelectedUserId(newUserId)
  ;

  const selectedUserObj = USERS_DATA.find(
    (element) => element.id === selectedUserId
  );

  return (
    <App selectedUserId=selectedUserId handleClick=handleClick 
    selectedUserObj=selectedUserObj />  
    )

最后是 App.js:

import "./styles.css";
import  USERS_DATA  from "./UserData";

export default function App(props) 

  const selectedUserObj = props.selectedUserObj;
  const handleClick = props.handleClick;

  return (
    <div className="App">
      <div className="list">
        <ul>
          USERS_DATA.map((user) => (
            <li onClick=() => handleClick(user.id) key=user.id>
              user.user_name
            </li>
          ))
        </ul>
      </div>
      <div className="panel">
          <p>selectedUserObj ? `$selectedUserObj.first_name $selectedUserObj.last_name 
          - $selectedUserObj.occupation` : 'Select a user'</p>
          <p>selectedUserObj ? `$selectedUserObj.catch_phrase` : '' </p>
      </div>
    </div>
  );

这就是它的样子:Screenshot_UserData_App

这个任务的重点是学习如何使用不同的组件来简化每个组件的功能,以及做一个道具类型检查——我还没有做过。我发现很难掌握如何将我的应用程序的逻辑拆分为两个组件 - 当我在一个组件中创建应用程序时,它运行良好。拆分后,我造成了混乱。有人可以启发我吗?谢谢!!!

【问题讨论】:

溢出的东西对我来说很好。除了一些小的语法改进外,我觉得其他一切都很好。 感谢您的浏览!好吧,不知何故,它在控制台上说 handleClick 不是一个函数——所以每当我点击一个用户时,它都会抛出一个类型错误。对不起,我忘了说这个。如果您好奇或有带宽,这里是沙箱的链接:codesandbox.io/s/user-data-app-with-prop-types-tkphx?file=/src/… 在 index.js 中你需要传递 AppContainer 而不是 App 组件。 codesandbox.io/s/… 谢谢你,拉杰迪普! :) 哈哈,好吧,我什至没有注意到这一点。 【参考方案1】:

我尝试使用您附加的代码框链接打开您的项目,但它完全崩溃了。答案很简单 - 您在默认情况下导出 App 时使用花括号导入 App。

import  App  from './App'; //get rid of curly braces

其余的工作正常,也许你已经解决了问题?

我要与您分享的另一件事 - 当您像这样传递句柄函数时

<li onClick=() => handleClick(user.id) key=user.id>
  user.user_name
</li>

你让 React 为每个人创建特殊的功能。所以最后你在内存中有很多函数,它们几乎相同,只是有不同的 id。最好将 id 存储在您的列表项中,然后通过事件将 id 传递给您的处理函数,该事件将由捕获整个列表(in)点击的一个函数处理

function handleClick(e) 
  setActive(+e.target.dataset.id) // "+" here converts string value from data to number 

...
<ul onClick=handleClick>
  USERS_DATA.map((user) => (
    <li data-id=user.id key=user.id>
      user.user_name
    </li>
  ))
</ul>

这将起作用,因为单击目标“li”将被其父组件“ul”捕获。现在您只有一个灯光功能。希望对您有所帮助。

【讨论】:

非常感谢您分享这个!确实很有帮助!我不知道我可以这样做。

以上是关于如何从使用状态挂钩的功能性父组件传递道具?的主要内容,如果未能解决你的问题,请参考以下文章

如何将值从组件传递给道具并设置状态

如何将道具从功能组件传递到类组件

我可以使用react中的useEffect挂钩从子级设置父级的状态

如何使用从 React 中的子组件获取的数据更新父组件中的状态

Array.map 中的 React 功能组件在将函数作为道具传递时总是重新渲染

将异步结果从父组件传递给子组件反应功能组件