如何在 React 功能组件之间传递数据?

How do I pass data between React Functional Components?

目前,我正在尝试将一段特定的数据,即用户的 name,从一个功能组件 <User/> 组件传递到另一个 <Profile /> 组件,当用户导航到某个页面时。

这是我的代码:

User.js

import React from 'react';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import { withRouter } from 'react-router-dom';

function User(props) {
    
    return (
        <div>
            <Link to={`/${props.username}`}>
                <hr />
                <p>
                    ({props.name}) {props.username}
                </p>
            </Link>
        </div>
    )
}


const mapStateToProps = state => ({});

export default connect(mapStateToProps)(withRouter(User));

UsersList.js

import React from 'react';
import { withRouter } from 'react-router-dom';

import User from './User';

function UsersList() {
  return (
    <div>
      <h1>Users</h1>
      <User username="john_smith" name="John Smith"/>
      <User username="james_madison" name="James Madison"/>
      <User username="george_washington" name="George Washington"/>
    </div>
  );
}

export default (withRouter(UsersList));

Feed.js

import React from "react";
import { Container } from "react-bootstrap";
import UsersList from "./users/UsersList";

function Feed() {
  return (
    <div>
      <Container>
        <UsersList/>
      </Container>
    </div>
  );
}

export default Home;

App.js

import React from "react";
import { Route, Switch } from "react-router-dom";
import Feed from './components/Feed';
import Profile from "./components/Profile";
import Root from "./Root";


function App() {
  return (
    <Root>
      <Switch>
        <Route exact path="/" component={Feed} />
        <Route exact path="/:username" component={Profile} />
      </Switch>
    </Root>
  );
}

export default App;

这是当前 <Profile /> 页面 - 我只是想将用户名 而不是用户名 传递到一对 <h1></h1> 标签中:

Profile.js

import React from "react";
import { Container } from "react-bootstrap";

function Profile(props) {
  return (
    <Container>
      <h1>I SIMPLY WANT TO PASS THE USERS NAME HERE</h1>
    </Container>
  );
}

export default Profile;

感谢任何帮助或指导!

这是一个可以使用全局状态管理器的示例。考虑像 reduxcontext providers 这样的东西。就功能组件而言,越来越多的人正在远离 redux 并使用带有 useContext 钩子 (more information can be found here) 的上下文提供程序。就快速解决方案而言,使用 App 状态始终是可能的,但是当试图将它们传递到组件层次结构的同一级别时,传递道具可能会变得非常混乱。

你必须使用 Redux。这就是我喜欢它的方式-

首先安装redux模块:npm install react-redux

src/components/Profile.js

使用 mapStateToProps 函数映射 redux store 中的用户数据

  import React from "react";
  import { Container } from "react-bootstrap";
  import { connect } from 'react-redux';

 function Profile( props) {
 let users = props.users
 let userName = window.location.pathname.substring(1);
 var name;
  users.forEach((element) => {
   if(element['username'] === userName){
   name = element['name'];
 }
 });
   return (
   <Container>
     <h1>I SIMPLY WANT TO PASS THE USERS NAME HERE</h1>
     {name }
   </Container>
    );
  }
  const mapStateToProps = state => ({
   users: state.users,
   });
 export default connect(mapStateToProps)(Profile);

/src/action.js

这里我已经初始化了所有的用户初始值,理想情况下是你将从另一个系统获得的用户数据,在这种情况下你将使用 Thunk 或 Saga 进行副作用操作

   export const LOAD_USER = 'LOAD_USER';

 const users = [{ username:'john_smith', name: 'John Smith' }, 
            { username:'james_madison', name: 'James Madison' }, 
            {username:'george_washington', name: 'George Washington'}];

   export const loadeUser = () => ({
   type: LOAD_USER,
   payload: { users },
   });

/src/reducer.js

我只是将所有用户数据传递给状态对象

     import { LOAD_USER } from './actions';

    export const users = (state = [], action) => {
   const { type, payload } = action;
   switch (type) {
   case LOAD_USER :{
    const { users } = payload;
    return users;
   }
   default:
    return state;
  }
  }

/src/components/User.js

  import React from 'react';
  import { Link } from 'react-router-dom';

 function User({user}) {
  return (
    <div>
        <Link to={`/${user.username}`}>
            <hr />
            <p>
                ({user.name}) {user.username}
            </p>
        </Link>
    </div>
    )
  }
  export default User;

/src/components/UsersList.js

这里我们必须同时使用 mapDispatchToProps 和 mapStateToProps,以便通过 useEffect 挂钩在组件加载时执行调度操作。

    import React, { useEffect } from 'react';
    import { withRouter } from 'react-router-dom';
    import { loadeUser } from '../actions';
    import { connect } from 'react-redux';
    import User from './User';


  function UsersList({ users = [] , startLoadingUsers}) {
   useEffect(() => {
   startLoadingUsers();
   }, []);

 return (
  <div>
  <h1>Users</h1>
  { 
    users.map(user => <User user={user} />)
  }
  </div>
  );
 }

 const mapStateToProps = state => ({
  users: state.users,
 });

const mapDispatchToProps = dispatch => ({
 startLoadingUsers: () => dispatch(loadeUser()),
});

export default connect(mapStateToProps, mapDispatchToProps) 
(withRouter(UsersList));

/src/App.js

使用 BrowserRouter 环绕不同的路由

   import React from "react";
  import { Route, Switch,BrowserRouter as Router, } 
   from "react-router-dom";
  import Feed from './components/Feed';
   import Profile from "./components/Profile";

   function App() {
   return (
   <Router>
     <Switch>
      <Route exact path="/" component={Feed} />
      <Route exact path="/:username" component={Profile} />
      </Switch>
    </Router>
   );
  }
 export default App;

/src/index.js

最后,将商店作为 App 组件的包装器挂钩,以便所有组件都可以使用 Redux 商店,这是由 Provider 完成的。

       import React from 'react';
       import ReactDOM from 'react-dom';
       import App from './App';
        import { Provider } from 'react-redux';
       import { configureStore } from './store';

       const store = configureStore();

       ReactDOM.render(
       <Provider store={store}>
         <App />
       </Provider>,
        document.getElementById('root')
       );

/src/store.js

        import { createStore, combineReducers } from 'redux';
        import { users } from './reducer';

         const reducers = {
         users,
         };

        const rootReducer = combineReducers(reducers);
        export const configureStore = () =>
         createStore(
           rootReducer,
            window.__REDUX_DEVTOOLS_EXTENSION__ &&
            window.__REDUX_DEVTOOLS_EXTENSION__(),
        );

最后的结果