如何将props从子组件传递到父组件再传递到ReactJS中的另一个子组件?

I'm currently creating a search bar where App is the parent and Header, Home are the children. I'm trying to pass the input from Header to Home via App but it seems that when I try to load in {this.state.searchValue} it does nothing.

I'm lost of where I am wrong in my code. I'm also using Route to route the props from Header to Home.

这是我的代码:

Header.js(孩子1)

class Header extends Component {
  constructor(props) {
    super(props);
    this.state = {
      search: "",
    };
  }

  onChange = (event) => {
    this.setState({ search: event.target.value });
  };

  submitSearch = (event) => {
    event.preventDefault();
    console.log(this.state.search);
    this.props.passSearchData(this.state.search);
  };

  render() {
    return (
      <React.Fragment>
        <nav className="navbar navbar-expand-lg navbar-light bg-light">
          <form className="form-inline">
                <input
                  className="form-control mr-sm-2"
                  type="text"
                  placeholder="Search"
                  onChange={this.onChange}
                />
                <button
                  className="btn btn-danger"
                  type="submit"
                  onClick={this.submitSearch}
                >
                  Search
                </button>
              </form>
        </nav>
      </React.Fragment>
    );
  }
}

export default Header;

App.js(父)

class App extends Component {
  constructor() {
    super();
    this.state = {
      searchValue: "",
    };
  }

  handleSearchData = (search) => {
    this.setState({ searchValue: search });
  };

  componentDidMount() {
    this.props.getItems();
  }

  render() {
    return (
      <div className="App">
        <Router>
          <Header passSearchData={this.handleSearchData} />
          <Route
            exact
            path="/"
            render={(props) => (
              <Home {...props} searchValue={this.state.searchValue} />
            )}
          />
        </Router>
        <Footer />
      </div>
    );
  }
}

Home.js

class Catalog extends Component {
  constructor(props) {
    super(props);
    this.state = {
    };
  }
render() {
return (
      <div>
        <p>{this.props.searchValue}</p>
      </div>
    );
  }
}
评论
  • 喵oo
    喵oo 回复

    请检查以下示例,在该示例中,我们从孩子向父母发送道具,然后从父母向另一个孩子发送道具:

    父组件

    import React, {useEffect, useState} from 'react';
    import Child from "./Child";
    import Sibling from "../Sibling";
    
    function CParent(props) {
    
        const [status, setStatus] = useState(false);
    
        function setOpeningValue(status) {
            console.log('From Child to Parent:' + status);
            setStatus(status);
        }
        return (
            <div>
                <Child setOpeningValue={setOpeningValue}/>
                <Sibling status={status}/>
            </div>
        );
    }
    export default CParent;
    

    子组件

    import React, {useEffect, useState} from 'react';
    
    // Child to Parent communication
    function Child(props) {
        const {setOpeningValue} = props;
        const [isOpen, setOpen] = useState(false);
    
        function clickHandler() {
            setOpen(!isOpen);
            setOpeningValue(`changes is ${!isOpen}`);
        }
        return (
            <div>
                <button onClick={clickHandler}>Open</button>
            </div>
        );
    }
    export default Child;
    

    同级组件

    import React, {useEffect, useState} from 'react';
    
    function Sibling(props) {
        const {status} = props;
        const [isOpen, setOpen] = useState(false);
    
        return (
            <div>
                From Child to Parent to Another Child (Sibling) {status}
            </div>
        );
    }
    export default Sibling;
    
  • mex
    mex 回复

    我认为使用反应上下文更好地解决这个问题

    First u declare your own Provider to act as intermediary between components. The context will save all the application state. and to consume at your components, simply use useContext and pass the Context u want to use, at this useCase, i call it AppContext. by using the same context, your components get the same state and trigger update immediately

    我提供的解决方案是使用功能组件。如果u使用的是Component类,则只需创建一个功能组件,然后将上下文传递给该类组件

    import React, { useContext, useState } from 'react'
    
    const AppContext = useContext({})
    
    const AppProvider = props => {
      const [currentState, setCurrentState] = useState(null)
      
      const handleState = value => {
        setCurrentState(value)
      }
      
      const contextValue = { handleState, currentState }
      
      return (
        <AppContext.Provider value={contextValue}>
          {props.children}
        </AppContext.Provider>
      )
    }
    
    const Child1 = props => {
      const { handleState } = useContext(AppContext)
      
      const handleClick = e => {
        handleState(e.target.values)
      }
      
      return (
        <button onClick={handleClick}>Change State</button>
      )
    }
    
    const Child2 = props => {
      const { currentState } = useContext(AppContext)
      
      return (
        <h1>{currentState}</h1>
      )
    }
    
    const Parent = props => {
      
      return (
        <Router>
          <AppProvider>
            <Route component={Child1} />
            <Route component={Child2} />
          </AppProvider>
        </Router>
      )
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>