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

时间:2020-05-11 07:58:13

标签: javascript reactjs react-native react-router react-component

我当前正在创建一个搜索栏,其中App是父级,HeaderHome是子级。我正在尝试通过Header将输入从Home传递到App,但是似乎当我尝试加载{this.state.searchValue}时却无济于事。

我迷失了我的代码错误之处。我还使用Route将道具从Header路由到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>
    );
  }
}

1 个答案:

答案 0 :(得分:1)

我认为使用反应上下文可以更好地解决此问题,因为在路由之间传递状态非常痛苦

首先,您声明您自己的提供者以充当组件之间的中介。 上下文将保存所有应用程序状态。并使用您的组件,只需使用useContext并传递您要使用的Context,在这个useCase中,我将其称为AppContext。通过使用相同的上下文,您的组件将获得相同的状态并立即触发更新

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

import React, { useContext, useState } from 'react'

const AppContext = React.createContext({})

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>