【问题标题】:Passing a function works, but doesn't change the variable传递函数有效,但不会更改变量
【发布时间】:2022-01-23 17:24:54
【问题描述】:

我正在将一个函数传递给链接中的另一个组件。在另一个组件中,我对 api 进行查询,当执行查询时,我返回上一页并执行“openFromLogin”函数。该函数执行,因为它返回console.log,但变量仍然为false。

我想这样做,以便在登录并重定向后自动打开模式。

请帮忙,谢谢:)

import React, { useState } from 'react';
import { Link } from 'react-router-dom';
import Modal from 'react-modal';

function ProductSidebarOne(props) {
  const [openPricing, setOpenPricing] = useState(false);
  
  const openFromLogin = () => {
    setOpenPricing(true);
    console.log("done");
  }
  console.log(openPricing);

  return (
    <>
      <Link to={{ pathname: `/login`, state: { from: props.location.pathname }, openFromLogin }} className="font-orange font-semibold">Log in</Link>
      <Modal
        isOpen={openPricing}
        shouldFocusAfterRender={false}
        className="pricing-popup"
        closeTimeoutMS={10}
      >
        <div className="modal-dialog modal-dialog-centered" role="document">
          <div className="modal-content">
            <div className="modal-body">
              <button type="button" className="close" aria-label="Close" style={{ position: 'absolute', right: '0', top: '0' }}>
                <span aria-hidden="true">&times;</span>
              </button>
            </div>

            <div className="modal-footer">
              <button type="button" className="btn btn-link btn-sm">Close</button>
              <button type="submit" className="btn btn-primary btn-sm">Send</button>
            </div>
          </div>
        </div>
      </Modal>
    </>
  )
}

export default ProductSidebarOne;
import React, { useState } from 'react';
import axios from 'axios';

import { setUserSession } from '../../../../utils';

function Login(props) {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const openFromLogin = props.location.openFromLogin;

  const handleLogin = (e) => {
    e.preventDefault();

    axios.post("api url", {
      email: email,
      password: password
    })
    .then(response => {
      setUserSession(response.data);
      props.history.push(props.location.state.from, openFromLogin());
    });
  }

  return (
    <div className="login-page">
      <form onSubmit={handleLogin} className="mb-0">
        <input type="text" className="form-control" value={email} onChange={e => setEmail(e.target.value)} />
        <input type="password" className="form-control" value={password} onChange={e => setPassword(e.target.value)} />
        <div className="form-footer">
          <button type="submit" className="btn btn-primary">Log in</button>
        </div>
      </form>
    </div>
  )
}

export default Login;

【问题讨论】:

    标签: reactjs


    【解决方案1】:

    复制于Pass props in Link react-router

    AFAIK 你不能用Link 做到这一点。您必须传递路径或查询参数,因为 Link 基本上只是一个 url 的锚点。

    您可以改为使用context 设置“全局”状态,该状态在成功登录后被操纵。然后您的ProductSidebarOne 可以订阅、“使用”该上下文并对它做出反应,如果它满足要求。

    示例:设置一个AuthenticationContext 并在成功登录后将loggedIn 设置为trueuseContext 用于ProductSidebarone 中的AuthenticationContextloggedIn 上的useEffect 从上下文到setOpenPricing(true) .

    我希望这可以澄清它。

    编辑:

    我将尝试提供一个最小的示例,包括缺少的提供程序。请注意,这未经测试。

    import React, { createContext } from 'react';
    
    // Create and export context
    export const AuthenticationContext = createContext({
      loggedIn: false,
      setLoggedIn: () => {},
    });
    
    //e.g. App.js
    import { AuthenticationContext } from 'PATH';
    
    const App = () => {
       ...
       // Hold state for context
       const [loggedIn, setLoggedIn] = useState(false);
    
       return (
          ...
          // Provide context to child components in app
          <AuthenticationContext.Provider value={{loggedIn, setLoggedIn}}>
             ...
          </AuthenticationContext.Provider>
       )
    }
    
    import React, { useState, useContext, useEffect } from 'react';
    import { Link } from 'react-router-dom';
    import Modal from 'react-modal';
    
    import { AuthenticationContext } from '../../../others/common/context';
    
    function ProductSidebarOne(props) {
      const [openPricing, setOpenPricing] = useState(false);
    
      // Connect to context
      const { loggedIn } = useContext(AuthenticationContext);
    
      // Here we can use the state inside context
      // e.g. react to change in context
      useEffect(() => {
         if(loggedIn) setOpenPricing(true)
      }, [loggedIn])
    
      return (...)
    }
    
    import React, { useState, useContext } from 'react';
    import axios from 'axios';
    
    import { setUserSession } from '../../../../utils';
    import { AuthenticationContext } from '../common/context';
    
    function Login(props) {
      ...
    
      const { loggedIn, setLoggedIn } = useContext(AuthenticationContext);
    
      const handleLogin = (e) => {
        e.preventDefault();
    
        axios.post("api url", {
          email: email,
          password: password
        })
        .then(response => {
          setUserSession(response.data);
          // Manipulate state from any child
          setLoggedIn(true);
          props.history.push(props.location.state.from);
        });
      }
    
      return (...)
    }
    
    export default Login;
    

    【讨论】:

    • 我已经尝试过这个解决方案,但它不起作用或者我做错了什么。问题可能是供应商没有连接组件,我无法连接它们。我会把代码放在下面。
    • 是的,您必须用提供者包装将使用上下文(可能是您的整个应用程序?)的组件。该提供者最终持有身份验证状态,这将触发所有连接组件的重新渲染。
    • 我用一个包括提供者的例子编辑了答案。请看看是否有帮助。
    • 它有效,谢谢! :)
    猜你喜欢
    • 2013-11-05
    • 1970-01-01
    • 2014-04-15
    • 1970-01-01
    • 1970-01-01
    • 2012-08-04
    相关资源
    最近更新 更多