Javascript 如何更新组件装载上的路径?

Javascript 如何更新组件装载上的路径?,javascript,reactjs,redux,react-router-dom,Javascript,Reactjs,Redux,React Router Dom,我在一个组件中有一个登录/注册表单,我正在尝试相应地更新URL路径。但我有几个问题要解决我正在使用Firebase FetchSigningMethodsForemail()检查用户是否存在,如果是空数组,则是新用户。 当propnew为真时。它将呈现创建密码输入,并将URL从/login更新到/signup。理想输出:键入任意随机电子邮件地址。url从登录->注册和创建密码输入挂载更改 当前的输出是,当且仅当我单击了用…包装的Form.Item时,/signup才会触发(显示) 如果我直接键入

我在一个组件中有一个登录/注册表单,我正在尝试相应地更新URL路径。但我有几个问题要解决我正在使用Firebase FetchSigningMethodsForemail()检查用户是否存在,如果是空数组,则是新用户。

  • 当prop
    new
    为真时。它将呈现创建密码输入,并将URL从/login更新到/signup。理想输出:键入任意随机电子邮件地址。url从登录->注册和创建密码输入挂载更改
  • 当前的输出是,当且仅当我单击了用
    包装的Form.Item时,/signup才会触发(显示)

  • 如果我直接键入path/signup,我如何触发redux来分派将更新
    new
  • 我尝试使用useRouteMatch获取路径,如果它等于/signup,则发送一个操作以切换
    新建
    ,但这样做会导致太多的重新渲染错误

    if(match.path === "/signup")
    {
         dispatch(new());
    }
    
    当前路线:

    <Switch>
      <Route path="/signup" component={Login} />
      <Route path="/login" component={Login} />
    </Switch>
    
    
    
    Login.js

      const dispatch = useDispatch();
      const { new } = useSelector(
        state => state.auth
      ); 
      const match = useRouteMatch();
      if(match.path === "/signup)
      {
         dispatch(new());
      }
    
      return (
        <Form>
            Email
          <Form.Item>
              <Input placeholder="Username" />
          </Form.Item>
    
            {new ? (
              <div>
              <Link to="/signup">
                Create password
                <Form.Item>
                    <Input.Password placeholder="Password"/>
                </Form.Item>
               </Link>
              </div>
            ) : (
              <div>
                Enter your password
                <Form.Item>
                    <Input.Password placeholder="Password"/>
                </Form.Item>
              </div>
          )}
          </Link>
          {new ? (
            <Button>
              Sign up
            </Button>
          ) : (
            <Button>
              Log in
            </Button>
          )}
        </Form>
      );
    });
    
    const dispatch=usedpatch();
    常量{new}=useSelector(
    state=>state.auth
    ); 
    const match=useRouteMatch();
    if(match.path==”/注册)
    {
    分派(新的());
    }
    返回(
    电子邮件
    {新的(
    创建密码
    ) : (
    输入您的密码
    )}
    {新的(
    注册
    ) : (
    登录
    )}
    );
    });
    
    如果我理解正确,您希望在组件安装阶段后发送此操作一次。在这种情况下,挂钩可能非常适合:

    import { useEffect } from "react";
    
    ...
    
    const match = useRouteMatch();
    
    const onMount = () => {
      /* This callback is invoked after mount */
      if(match.path === "/signup)
      {
         dispatch(new());
      }
    }
    
    /* The effect hook runs the following callback as a side effect */
    useEffect(() => {
      onMount();
    }, []); /* Empty array causes the effect to only run once (on mount) */
    
    有关为什么空数组会导致effect回调触发一次的详细信息,请参阅

    还有一个小建议——考虑将代码< >新()/代码>函数和<代码>新< /COD>变量变为其他东西(也许<代码>新< /代码>?),看到<代码>新< /代码>是保留关键字。

    希望有帮助

    更新 您可以采用以下“非重复”方法来实现与您提供的链接类似的登录/注册流程:

    const { useState } from "react";
    
    const AuthForm = () => {
    
      /* Define state shape */
      const [state, setState] = useState({ 
        username : "", 
        password : "", 
        isNew : false 
      });
    
      /* Field update helpers */
      const setUsername = (username) => setState(s => ({ ...s, username }))
      const setPassword = (password) => setState(s => ({ ...s, password }))
    
      const login = async () => {
        const { username, password } = state;
        /* login logic */
      }
    
      const signup = async () => {
        const { username, password } = state;
        /* signup logic */
      }
    
      const checkUsername = async () => {
    
        /*
        const response = await fetch("/api/check-username-exists", { 
            method : "POST", 
            body : JSON.stringify({ userNameToCheck : state.username })
        })
    
        // say that response.found is true when user name we checked 
        // does exist in database
        setState(s => ({ ...s, isNew : !response.found }));
        */
      }
    
      const renderFields = () => {
    
        if(!username) {
          return <>
            <Form.Item>
              <Input placeholder="Username" 
                     onChange={e =>setUsername(e.target.value)} />
            </Form.Item>
            <Button onClick={checkUsername}>
              Continue
            </Button>
          </>
        }
        else {
          return <>
          <p>Login as { state.username }</p>
          {
            state.isNew ? (<div>
              <p>Create password</p>
              <Form.Item>
                <Input.Password placeholder="Password"
                    onChange={e => setPassword(e.target.value)}/>
              </Form.Item>
              <Button onClick={signup}>
                Sign up
              </Button>
            </div>) : (<div>
              <p>Enter your password</p>
              <Form.Item>
                <Input.Password placeholder="Password" 
                     onChange={e => setPassword(e.target.value)}/>
              </Form.Item>
              <Button onClick={login}>
                Log in
              </Button>
            </div>)
          }
          </>
        }
      }
    
      return (<Form>{renderFields()}</Form>);
    }
    
    const{useState}来自“react”;
    常量AuthForm=()=>{
    /*定义状态形状*/
    const[state,setState]=useState({
    用户名:“”,
    密码:“”,
    isNew:错误
    });
    /*字段更新帮助程序*/
    const setUsername=(username)=>setState(s=>({…s,username}))
    const setPassword=(password)=>setState(s=>({…s,password}))
    const login=async()=>{
    const{username,password}=state;
    /*登录逻辑*/
    }
    const signup=async()=>{
    const{username,password}=state;
    /*注册逻辑*/
    }
    const checkUsername=async()=>{
    /*
    const response=wait fetch(“/api/check username存在”,{
    方法:“张贴”,
    正文:JSON.stringify({userNameToCheck:state.username})
    })
    //当我们检查用户名时,假设response.found为true
    //是否存在于数据库中
    setState(s=>({…s,isNew:!response.found}));
    */
    }
    常量渲染字段=()=>{
    如果(!用户名){
    返回
    setUsername(e.target.value)}/>
    继续
    }
    否则{
    返回
    以{state.username}身份登录

    { state.com是新的吗( 创建密码

    setPassword(e.target.value)}/> 注册 ) : ( 输入您的密码

    setPassword(e.target.value)}/> 登录 ) } } } 返回({renderFields()}); }

    请记住,这只是用于说明“非重复性”的框架代码“实施表格的方式。它需要通过对后端/API等的适当调用来完成,但希望这能为您提供一些如何实现所需的想法:-)

    可能使用本地状态来控制而不是redux存储

    const [isNew, setIsNew] = useState(location && location.pathname === '/signup')
    
    function handleEmailCheck(event) {
      // use Firebase fetchSignInMethodsForEmail() to check the email
      // and use setIsNew() & history.pushState() to update address bar render content
    }
    
    return (
      <Form>
          Email
        <Form.Item>
            <Input placeholder="Username" onBlur={handleEmailCheck} />
        </Form.Item>
        ...
    
    const[isNew,setIsNew]=useState(location&&location.pathname===='/signup')
    函数handleEmailCheck(事件){
    //使用Firebase FetchSignInMethodForEmail()检查电子邮件
    //并使用setIsNew()和history.pushState()更新地址栏呈现内容
    }
    返回(
    电子邮件
    ...
    
    是的,这与我的代码不同。这应该可以解决2。你知道我如何解决问题1吗?另外,Hook useEffect缺少依赖项:“dispatch”和“match.path”。包括它们或删除依赖项数组。我如何克服这一点?只是更新了代码以解决该警告-我不太确定我是否理解第一个point抱歉?您希望在用户单击“注册”按钮后显示密码表单项-是否正确?第一个实例将显示用户名输入和带有URL/Login的登录按钮。当我输入用户名时(在用户名输入中)和未找到新的将变为现实。这将显示“创建密码输入和注册”按钮,并将URL更改为/signup。希望这更容易理解。此外,警告尚未解决。这不是一个大问题,但最好能让您大吃一惊。您可能会发现直接在组件中管理它更容易(即无重复/调度/等)。您可以在本地
    useState
    确定提供的用户名是否存在用户,然后将
    New
    更新为本地组件状态,以控制注册/登录表单项的呈现。我认为我的问题是,当New=true时,在组件装载时,我希望URL更改/登录到/signup。我当前拥有的是/signupURL仅在我实际必须单击任意位置时应用