【问题标题】:ReactJS: Pass sibling component data into conditional componentsReactJS:将兄弟组件数据传递给条件组件
【发布时间】:2021-06-10 12:54:11
【问题描述】:

我的目录结构如下图所示。

LoginComponent 登录时,我想将登录数据传递给UserProfileComponent,如果未登录,则默认加载DefaultCompoent

为此,我对组件进行了如下管理。

LandingComponent.js
export default function LandingComponent(props) {

  const [isLoggedIn, setIsLoggedIn] = useState(false);
  const [userName, setUserName] = useState('')
  useEffect(() => {
    setIsLoggedIn(true)
  });

  return (
    <main>
    {
      isLoggedIn ? <UserProfileComponent setUserName={setUserName} /> : <DefaultComponent userName={userName} />
    }
      
    </main>
  )
}

DefaultComponent.js

export default function DefaultComponent(props) {
    return (
        <p>Hello User</p>
    )
}

UserProfileComponent.js

export default function UserProfileComponent(props) {
    return (
        <p>Hello {userName}</p>
    )
}

LoginComponent.js

export default function LoginComponent(props) {
    const [email, setEmail] = useState("");
    const [userPassword, setPassword] = useState("");

    const loginUser = async event => {
    event.preventDefault()
    axios.post(`{api_endpoint}/login`, data)
    .then((response) => {
        const userDetails = response.data
    })
  })

  return ( 
    <form onSubmit={loginUser}>
      <input
        value={email}
        type="email"
        onChange={(e) => setEmail(e.target.value)}
      />
      <input
        value={userPassword}
        onChange={(e) => setPassword(e.target.value)}
        type="password"
        id="password"
        placeholder="Password"
        required
      />
      <div className="col-2">
        <input type="submit" name="" value="Login" />
      </div>
    </form>
  )
}

那么,如何使用钩子将 login_api 响应数据从 LoginComponent 传递给 UserProfileComponent

【问题讨论】:

  • 使用 Redux 或 Context API。

标签: javascript reactjs react-hooks next.js


【解决方案1】:

使用context api

  • 创建和导出上下文:

    export const AuthContext = React.createContext();
    
  • pages/index.js 中添加新状态并将组件包装到上下文提供程序中:

    export default function Home() {
    const [userData, setUserData] = React.useState(null);
    
    return (
      <React.Fragment>
        <Head>
          <title>Sample App</title>
        </Head>
        <AuthContext.Provider value={{ userData, setUserData }}>
          <HeaderComponent />
          <LandingComponent />
        </AuthContext.Provider>
      </React.Fragment>
    );
    }
    
  • 访问和更新LoginComponent中的上下文:

    export default function LoginComponent(props) {
    const [email, setEmail] = useState("");
    const [userPassword, setPassword] = useState("");
    const { setUserData } = React.useContext(AuthContext);
    
    const loginUser = async event => {
      event.preventDefault();
      axios.post(`{api_endpoint}/login`, data).then(response => {
        // Update the context variable
        setUserData(response.data);
      });
    };
    
    return <div />;
    }
    
  • 访问UserProfileComponent中的上下文:

    export default function UserProfileComponent(props) {
    const { userData } = React.useContext(AuthContext);
    
    if (!userData) {
      return "Loading...";
    }
    
    // do something with userData
    
    return <p>Hello {userName}</p>;
    }
    

如您所见,您可以使用useContext 挂钩来访问这些值。另一种方法是将相应的组件包装在 &lt;AuthProvider.Consumer /&gt; 标记中。

编辑:

我更新了答案并将上下文移至 Home 组件。

【讨论】:

  • 好的!!!让我试试,会更新你。感谢您的超级快速响应。
  • 嘿,我试过这个并得到 TypeError: Cannot read property 'setUserData' of undefined prnt.sc/10lylt8,有什么线索吗?另请查看有关附加代码和框示例的更新问题。
  • LandingComponent 文件中有错字。它应该是 userData 而不是 userDate 并且在 UserProfile 中,在上下文的导入周围缺少 {}。
  • 同样在AuthContext.Provider 中你使用了{()} 而不是{{}}
  • 嘿,我已经修正了错别字,但仍然收到来自LoginComponentlf92f.sse.codesandbox.iocodesandbox.io/s/lucid-montalcini-lf92f?file=/components/… 的相同错误
【解决方案2】:

你可以通过两种方法解决这个问题

  1. 为兄弟创建父组件并在父组件中维护状态并将其作为道具传递给其子组件
  2. 使用 React context API 或 Redux 等状态管理工具来避免将 props 传递给子元素(Prop Drilling)

方法一:

创建一个新组件,例如:Parent.js

export default function Parent() {
//Maintain State here
const [isLoggedIn, setIsLoggedIn] = useState(false);

return (
  <main>
   {/*Pass your state to childs as prop*/}
   <ChildComponent1 isLoggedIn={isLoggedIn} />
   <ChildComponent2 isLoggedIn={isLoggedIn} />
  </main>
);
}

方法二:

使用 React Context API 或 Redux 进行状态管理

对于React Context,请查看本教程:https://youtu.be/35lXWvCuM8o

对于Redux,请查看本教程:https://youtu.be/CVpUuw9XSjY

【讨论】:

  • 是的,我已经在关注@Gh05d 的答案,但停留在某一点。感谢 youtube 参考链接。
猜你喜欢
  • 2018-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-02
  • 2019-12-30
  • 2018-07-27
  • 2017-06-13
  • 2017-12-01
相关资源
最近更新 更多