将数据从子组件传递到父组件无法正常工作

时间:2020-06-23 12:52:25

标签: javascript reactjs react-router

我正在将数据从子组件(标头组件)传递到父组件(应用程序组件)。我的想法:当我单击页眉组件中的创建按钮时,我想向应用程序组件发送信息以隐藏页眉和页脚。这是代码示例。

Header.jsx:

import React, { Component } from 'react';
import { Nav, Navbar, Button } from "react-bootstrap";

class Header extends Component {

constructor(props) {
    super();
    this.state = {
        showHeaderAndFooter: false
    };
}

onChangeChildComponent = () => {
    this.props.changeVisibilityOfHeaderAndFooter(this.state.showHeaderAndFooter);
}

render() {
    return (  
        <Navbar bg="dark" variant="dark">
            <Nav className="mr-auto">
                <Button href="/createGym" onClick={this.onChangeChildComponent.bind(this)}> Create </Button>
            </Nav>           
        </Navbar>
    );
}
}

导出默认标题;

App.js:

import React, { Component, Fragment } from 'react';
import './App.css';
import './components/header';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import Header from './components/header';
import Footer from './components/footer';
import Home from './components/home';
import CreateGym from './components/create-gym';
import Login from './components/authentication/login';

class App extends Component {

constructor() {
    super();
    this.state = {
        showHeaderAndFooter: true
    };
}

onChangeChildComponent (showHeaderAndFooter) {
    this.setState(
    {
        showHeaderAndFooter: showHeaderAndFooter
    });
}

Container = () => (
  <div>
      { this.state.showHeaderAndFooter && 
      <Header 
         changeVisibilityOfHeaderAndFooter = {this.onChangeChildComponent.bind(this)}
      />
      } 
      <div className="container">
          <Route exact path='/' component={Home} />
          <Route path="/createGym" component={CreateGym} />
          <Route path="/login" component={Login} />
      </div>
      { this.state.showHeaderAndFooter && <Footer /> } 
  </div>
  )

render() {
    console.log(this.state.showHeaderAndFooter);
    return (
        <BrowserRouter>
            <Switch>
                <Fragment>
                    { <Route component={this.Container}/> }
                </Fragment>
            </Switch>
        </BrowserRouter>  
    );
}
}

export default App;

问题是因为我的代码两次进入App构造函数。第一次,一切都很好,但是第二次,此布尔值showHeaderAndFooter再次设置为true,因为这是默认值。知道如何解决这个问题吗?

2 个答案:

答案 0 :(得分:2)

您不应该从孩子>父母那里传递。 react是单向的(这意味着数据只能以一种方式流动,而这种方式是向下流动)

要实现此目的,请将状态移到父级

class Parent extends React = {
   this.state = { showHeaderAndFooter: false }

   functionToToggleShowing = () => {
      this.setState({showHeaderAndFooter: !this.state.showHeaderAndFooter})
   }

  render() {
    return(
        <Child showHeaderAndFooter={this.state.showHeaderAndFooter} functionToToggleShowing={functionToToggleShowing} />
    )
  } 

}

这是pseduo代码,但本质上是将状态移至父级,然后将状态传递给子级,以及一种更改该状态的方法

答案 1 :(得分:1)

React允许通过道具将控制权从孩子传递给父母。

这是使其工作的三步过程:

步骤1:在“父级”中创建一个数据成员,该数据成员可操纵父级状态。

步骤2:将父母的数据成员作为道具发送给孩子。

步骤3:在孩子中,呼叫父母发送的用于响应事件的道具。

以下是使用上述技术将控制权从孩子传递给父母的演示:

该示例包含2个组成部分-

  • 父组件是 App.jsx
  • 子组件为 Header.jsx

父母有一个状态控制数据成员,称为“ hideHeader ”。

父母将名为 onClick 的道具 hideHeader 传递给孩子。

孩子调用父母发送的道具,以响应其 onClick 事件。

父组件-App.jsx

@echo off 
setlocal enabledelayedexpansion
goto :main
:main

setlocal
set /a current=0
set /a total=10

:loop
if !current! lss !total! (
echo stuffstuffstuffstuff.!current! > supercrap.txt
set /a current=!current!1+
        
goto :loop  
)   
endlocal
goto :eof

子组件-Header.jsx

import React, { Component } from 'react'
import Header from "./Header";

export default class App extends Component {

  constructor() {
    super();
    this.state = {
      showHeader: true
    }
  }


  {/*  A state-manipulating data member */}

  hideHeader = () => {
    this.setState({showHeader: false})
  }


  render() {
    return (
      <div>

        {/* State-manipulating data member sent as prop to child */}

        { this.state.showHeader &&
            <Header onClick={this.hideHeader} />
        }
      </div>
    )
  }
}

输出:

在单击“隐藏”按钮之前:

enter image description here

点击“隐藏”按钮后:

enter image description here