Programing

라우터 v5로 대응 오류: 개체가 반응 하위 개체로 유효하지 않음(찾은 항목: 키가 {child}인 개체)

c10106 2022. 4. 6. 22:16
반응형

라우터 v5로 대응 오류: 개체가 반응 하위 개체로 유효하지 않음(찾은 항목: 키가 {child}인 개체)

처음 접하는 앱이지만 한 번에 2개의 앱이 있는 웹 앱을 만들려고 한다.한 번에 두 개의 앱이 있다는 건, 두 개의 레이아웃이 있다는 뜻이야. 하나는 허가된 것이고 다른 하나는 허가되지 않은 거야.현재 로그인할 때 문제가 발생하여 성공적인 로그인을 리디렉션하려고 하면 다음 오류가 발생함:

오류: 개체가 리액션 하위 개체로 유효하지 않음(찾은 항목: 키가 {child}인 개체).자식 모음을 렌더링하려면 배열을 사용하십시오.

이것은 내가 어떻게 경로를 설정했는지 또는 내가 어떻게 방향을 바꾸었는지와 관련이 있을 것이다.

내 암호는 다 이단 말이야.오류는 일반적으로 hasesubmit 함수의 login.js에서 history.push 라인을 가리킨다.참고: 내 코드는 실제로 각 기능에 대해 여러 js 파일로 분할되어 있으며, 여기에 코드를 결합하여 코드가 좀 더 컴팩트해지도록 했다(이 예에 한해 가져오기도 결합했다).

업데이트: 내 문제를 ProtectionRoute 구성 요소로 좁힌 것 같지만, 여전히 문제가 무엇인지 완전히 알지 못한다.나는 내가 그 부품으로 가는 길을 지나가는 방법이라고 생각하지만 어떻게 고쳐야 할지 모르겠어.

import React, { useState,useEffect } from "react";
import { NavLink, Route, Switch, useRouteMatch, useHistory, useLocation, useParams } from 'react-router-dom';
import MainLayout from "../layouts/MainLayout";
import AuthLayout from "../layouts/AuthLayout";
import NotFound from "../pages/NotFound";
import Login from "../pages/Login";
import Welcome from "../pages/Welcome";
import Dashboard from "../pages/Dashboard";
import Locations from "../pages/Locations";
import ProtectedRoute from "./ProtectedRoute";
import Navbar from "react-bootstrap/Navbar";
import Nav from "react-bootstrap/Nav";
import { LinkContainer } from "react-router-bootstrap";
import { ReactComponent as Logo } from '../images/Logo.svg';
import { useAppContext } from "../libs/contextLib";
import { LinkContainer } from "react-router-bootstrap";
import { useAppContext } from "../libs/contextLib";
import axios from 'axios';
import Form from "react-bootstrap/Form";
import LoaderButton from "../components/LoaderButton";
import LoginImage from '../images/Login-Page-Image.png';
import FloatLabelTextBox from "../components/FloatLabelTextBox.js"
import { API_BASE_URL, ACCESS_TOKEN_NAME } from '../constants/apiConstants.js';
import { onError } from "../libs/errorLib";

export default function MainRoutes() {
    return (
        <Switch>
            <Route path={['/login', '/welcome']}>
                <AuthLayout>
                    <Route path='/login' component={Login} />
                    <Route path='/welcome' component={Welcome} />
                </AuthLayout>
            </Route>            
            <ProtectedRoute exact path={['/', '/locations']}>
                <MainLayout>                    
                    <Route path='/locations' component={Locations} />
                    <Route exact path='/' component={Dashboard} />
                </MainLayout>
            </ProtectedRoute>
            {/* Finally, catch all unmatched routes */}
            <Route>
                <NotFound />
            </Route>
        </Switch>
    );
}
function AuthLayout({children}) {    
    const { isAuthenticated } = useAppContext();
    return (
        <>
            <div className="AuthLayout container py-3">
                <Navbar collapseOnSelect expand="md" className="mb-3 login-nav">
                    <LinkContainer to="/welcome">
                        <Navbar.Brand href="/welcome" className="font-weight-bold text-muted">
                            <Logo />
                        </Navbar.Brand>
                    </LinkContainer>
                    <Navbar.Toggle />
                    <Navbar.Collapse className="justify-content-end">
                        <Nav activeKey={window.location.pathname}>
                            <LinkContainer to="/welcome">
                                <Nav.Link>Home</Nav.Link>
                            </LinkContainer>
                            <LinkContainer to="/login">
                                <Nav.Link>Login</Nav.Link>
                            </LinkContainer>
                        </Nav>
                    </Navbar.Collapse>
                </Navbar>
                <div className="Auth-Layout-Body">
                    {children}
                </div>
            </div>
        </>
    );
}
export default AuthLayout;    

function MainLayout({ children }) {
  const { isAuthenticated } = useAppContext();
  const { userHasAuthenticated } = useAppContext();
  const history = useHistory();
  
  function handleLogout() {
    userHasAuthenticated(false);
    console.log("log out");
    history.push("/login");
  }
  return (
    <>
      <div className="MainLayout container py-3">
        <Navbar collapseOnSelect expand="md" className="mb-3 login-nav">
          <LinkContainer to="/">
            <Navbar.Brand href="/" className="font-weight-bold text-muted">
              Location INTEL
          </Navbar.Brand>
          </LinkContainer>
          <Navbar.Toggle />
          <Navbar.Collapse className="justify-content-end">
            <Nav activeKey={window.location.pathname}>
              <LinkContainer to="/">
                <Nav.Link>Home</Nav.Link>
              </LinkContainer>
              <LinkContainer to="/locations">
                <Nav.Link>Locations</Nav.Link>
              </LinkContainer>
              {isAuthenticated ? (
                <Nav.Link onClick={handleLogout}>Logout</Nav.Link>
              ) : (<div></div>)}
            </Nav>
          </Navbar.Collapse>
        </Navbar>
        <div className="Main-Layout-Body">
          {children}
        </div>
      </div>
    </>
  );
}
export default MainLayout;    

export default function Login() {
    const history = useHistory();
    const [state, setState] = useState({
        email: "",
        password: "",
    });
    const { userHasAuthenticated } = useAppContext();
    const [isLoading, setIsLoading] = useState(false);

    const handleChange = (e) => {
        setState({
            ...state,
            [e.target.name]: e.target.value,
        })
    }

    function validateForm() {
        return state.email.length > 0 && state.password.length > 0;
    }

    function handleSubmit(event) {
        event.preventDefault();

        setIsLoading(true);

        const payload = {
            "email": state.email,
            "password": state.password,
        }
        try {    
            axios.post('/api/user/login', payload, {
                headers: {
                    useCredentails: true,
                    'x-api-key': ACCESS_TOKEN_NAME,
                    "Access-Control-Allow-Origin": "*"
                }
            })
                .then(function (response) {
                    console.log(response);
                    //console.log('status code = ' + response.status);
                    if (response.status === 200) {
                        console.log("logged in");
                        userHasAuthenticated(true);
                        history.push("/");
                    } else {
                        console.log("not logged in");
                    }
                })
                .catch(function (error) {
                    console.log(error);
                });

        } catch (e) {
            onError(e);
            setIsLoading(false);
        }
    }

    return (
        <div className="Login-Container">
            <div className="Login-Container-Row">
                <div className="Login">
                    <p className="Login-Header">Login</p>
                    <div className="Login-Form">
                        <Form onSubmit={handleSubmit}>
                            <Form.Group size="lg" controlId="email">
                                <FloatLabelTextBox
                                    inputLabel="EMAIL"
                                    inputAutoFocus="autofocus"
                                    inputType="email"
                                    inputName="email"
                                    inputPlaceholder="Email"
                                    inputValue={state.email}
                                    handleChangeProps={handleChange}
                                />
                            </Form.Group>
                            <Form.Group size="lg" controlId="password">
                                <FloatLabelTextBox
                                    inputLabel="PASSWORD"
                                    inputAutoFocus=""
                                    inputType="password"
                                    inputName="password"
                                    inputPlaceholder="Password"
                                    inputValue={state.password}
                                    handleChangeProps={handleChange}
                                />
                            </Form.Group>
                            <LoaderButton
                                block
                                size="lg"
                                type="submit"
                                isLoading={isLoading}
                                disabled={!validateForm()}>
                                Login
                            </LoaderButton>
                            <p>Not a member? <NavLink to="/register">Get Started Here</NavLink></p>
                        </Form>
                    </div>
                </div>
                <div className="Login-Image">
                    <img src={LoginImage} />
                </div>
            </div>
        </div>
    );
}

export default function ProtectedRoute({ children, ...props }) {
    const { isAuthenticated } = useAppContext();
    return (
        <Route 
          {...props} 
          render={props => (
            isAuthenticated ?
              {children} :
              <Redirect to='/login' />
          )} 
        />
    );
}

문제는 다음과 같다.

    <Route 
      {...props} 
      render={props => (
        isAuthenticated ?
          {children} : // <=== HERE!
          <Redirect to='/login' />
      )}

사용 중인 경우{children}마치 "JSX-Land"에 있는 것처럼... 하지만 그렇지 않아.넌 이미 한 세트 안에 있어{}JSX에 있는 건 자바스크립트랜드에 있다는 뜻이지

자바스크립트랜드에서는{children}"나에게 아이 하나만을 가진 물건을 만들어줘"라는 뜻이다.children". 그런 다음 JSX에 해당 개체를 삽입하려고 하면 React는 해당 개체를 사용하여 무엇을 해야 할지 모르므로 오류가 발생한다.

같은 코드에서 곱슬 교정기를 빼면 돼

    <Route 
      {...props} 
      render={props => (
        isAuthenticated ?
          children :
          <Redirect to='/login' />
      )}

P.S. 경로 태그는 태그일 뿐이므로, 이런 패턴을 많이 하고 있다면, 이 패턴을 만들고 싶을지도 모른다.AuthenticatedRoute태그를 지정하여 사용(이 용어를 반복하는 경우).

참조URL: https://stackoverflow.com/questions/66925817/react-with-router-v5-error-objects-are-not-valid-as-a-react-child-found-objec

반응형