【问题标题】:React - Passing data from child to parent componentReact - 将数据从子组件传递到父组件
【发布时间】:2022-06-30 17:56:50
【问题描述】:

我正在使用 类组件 构建一个 React 应用程序,但我确实遇到了一个问题。我制作了一个应用程序,它最初呈现一个搜索表单,根据用户在表单中输入的内容获取一些数据,并将它们显示在一个表格中。一切正常,我很高兴。当我引入页脚时,问题就来了;出于样式目的,我希望使页脚始终位于页面底部。一开始只有搜索表格,没有表格;如果我将页脚的 CSS 样式设置为“位置:粘性”,则无法使其停留在底部。它需要处于固定位置。但是当表格渲染时,固定位置不起作用,因为表格可能很长并且被渲染在页脚上。所以我需要动态更改页脚的 CSS:我想出的解决方案是我应该在 CSS 文件中为同一个页脚创建两种样式,一种位置固定,另一种相同但具有粘性位置。然后我需要在表格渲染之前和之后更改页脚的 id(以触发正确的“位置”),我可以在 React 中做到这一点。 基本上,我必须告诉 React:“当应用程序中没有渲染表格时,将页脚的 id 设置为“固定”以触发固定位置 CSS 样式。当用户获取数据时,表格被渲染,页脚的然后必须将 id 更改为“sticky”。 唯一的问题是:我不知道如何在我的应用程序组件的层次结构中做到这一点。截至目前,页脚在 App.js 组件中呈现,即:

App.js

import './App.css';
import { ButtonFetcher } from './components/ButtonFetcher';  // tutte importazioni non default, quindi 
import { MapEntry } from './components/MapEntry';  // vanno fatte tutte con il nome classe tra parentesi {}.
import { Header } from './components/Header';
import { ButtonMatches } from './components/ButtonMatches';
import { CustomFooter } from './components/CustomFooter';

function App() {
  return (
    <div className="App">
      <Header />
      <ButtonMatches />
      <CustomFooter />
    </div>
  );
}

export default App;

如您所见,App.js 呈现标题、搜索表单 (ButtonMatches) 和 CustomFooter。现在,在 ButtonMatches 内部,我实现了 fetch() 逻辑,该组件呈现 MatchTable 组件,如果数据不存在(用户没有进行搜索),则该组件为 null,如果用户这样做,它是一个完整的 html 表进行搜索。

ButtonMatches.js

// (some code ...)

render() 
    {       
        // (some code ...) 
        
        return (
                <div>
                  <div>
                    <form className="PlayerSearch" onSubmit={(event) => { event.preventDefault(); } }>
                        <input type="search" id="search-recent-matches" name="Gamertag" placeholder="Enter a Gamertag..."></input>
                        <button type="submit" onClick={ this.onClickNewSearch } >Search</button>
                    </form>
                  </div>
                  { WLKDcounter }
                  <MatchTable recentMatches={ this.data }/>
                  { more }
                </div> 
            );    
    }

所以,现在的问题是:我如何告诉 CustomFooter 表格已呈现?现在,CustomFooter 是在 App 组件中渲染的,它是 ButtonMatches 的父组件,它是 MatchTable 的父组件。所以基本上,MatchTable 组件必须能够对它的父组件 ButtonMatches 说“嘿!表格不为空,它被渲染了!”;那么 ButtonMatches 组件必须对其父组件 App 说“嘿!该表不为空,它已被渲染!”。然后 App 组件必须更改 CustomFooter 组件的 props 才能更改其状态,从而使他更改其 id 和样式。

第一个问题是从子级向父级发送数据是一种 React 反模式,我真的不知道如何避免这种情况。将页脚渲染到 MatchTable 组件中是唯一的解决方案,以符合 React 的单向数据流吗?从概念上讲,它看起来很丑,以至于表格组件呈现了页脚组件。我的网站的其他不同页面也需要相同的页脚。

第二个问题是,如果我将页脚留在 App 组件中,并找到一种方法(可能通过函数调用)通知表的父级它已呈现,我会陷入类似“反向道具钻" 因为 ButtonMatches 会从它的子 MatchTable 获得一个无用的信息,它只需要传递给它的父 App 组件。因为我现在不打算使用钩子(如果道具钻孔没有“反转”,useContext 会很有帮助),我会打破不同的 React 设计模式。

我找不到任何解决方案,我的网页设计师朋友已经尝试了她所能做的一切来改变风格,但无济于事。她告诉我,她绝对需要在表格呈现之前和之后更改页脚的“位置”属性,以便在两种情况下始终使页脚停留在页面底部。

【问题讨论】:

  • 请在沙盒中重新创建您的应用,以便回答者可以直接查看问题。

标签: css reactjs design-patterns react-props react-context


【解决方案1】:

基本上,您必须从其父级控制您的页脚。

因此,在您的 App 组件中,您可以添加一个新的状态属性,例如 isDataVisible。 您需要将它的 setter 传递给您的 ButtonMatches 并将其值传递给您的 Footer 以控制它自己的样式。

会是这样的:

const [isDataVisible, setIsDataVisible] = useState()

...

<ButtonMatches onToggleDataVisible={setIsDataVisible} />

...

<CustomFooter isSticky={isDataVisible} />

希望对你有帮助

【讨论】:

    【解决方案2】:

    您需要定义一个钩子并将状态更新函数作为道具传递 例如

    function App() {
    const [data,setData] = useState(/* initial value here */)
    
      return (
        <div className="App">
          <Header />
          <ButtonMatches updateValue={()=>setValue(val)}/> //call this.props.updateValue(inputState) at the component
          <CustomFooter value={value}//> //send value to footer
        </div>
      );
    }
    

    【讨论】:

      【解决方案3】:

      React - 将数据从子组件传递到父组件
      React - 将数据从父组件传递到子组件

      import { useEffect, useState } from "react";
      
      export default function App() {
        const data = (data) => {
          console.log("data", data);
        };
      
        const myData = {
          name: "hi this is my data"
        };
      
        return <Form onSubmit={data} myDatasa={myData} />;
      }
      
      const Form = (props) => {
        console.log("myData", props.myDatasa.name);
      
        const [choreDesc, setChoreDesc] = useState();
        const handleSubmit = (e) => {
          e.preventDefault();
          props.onSubmit(choreDesc);
        };
      
        const handlechange = (e) => {
          setChoreDesc(e.target.value);
        };
      
        return (
          <form
            onSubmit={(e) => {
              handleSubmit(e);
            }}
          >
            <label>Chore description:</label>
            <br />
            <input
              name="choreDesc"
              type="text"
              value={choreDesc}
              onChange={handlechange}
            />
            <br />
            <input type="submit" value="Add Log" />
          </form>
        );
      };
      ```
      

      【讨论】:

        猜你喜欢
        • 2021-01-26
        • 2019-02-27
        • 2017-04-20
        • 1970-01-01
        • 1970-01-01
        • 2020-10-22
        • 2017-06-10
        相关资源
        最近更新 更多