我试图使用 react app 制作表单,为此我制作了以下组件,但是当我在本地服务器上运行它时,它显示
错误:元素类型无效:应为字符串(对于内置组件)或类/函数(对于复合组件)但得到:对象。您可能忘记从定义组件的文件中导出组件,或者您可能混淆了默认导入和命名导入。
检查 App
的渲染方法。
Error while I run on localhost
请帮我解决这个问题。
我附上了组件文件 FormSuccess.js、useForm.js、validateInfo.js、App.js、App.css、FormSignup.js、Form.js、index.js、Form.css
import React from 'react';
import './Form.css';
const FormSuccess = () => {
return (
<div className='form-content-right'>
<h1 className='form-success'>We have received your request!</h1>
<img className='form-img-2' src='img/img-3.svg' alt='success-image' />
</div>
);
};
export default FormSuccess;
import useState from 'react';
import useEffect from 'react';
const useForm = (callback, validate) => {
const [values, setValues] = useState({
username: '',
email: '',
password: '',
password2: ''
});
const [errors, setErrors] = useState({});
const [isSubmitting, setIsSubmitting] = useState(false);
const handleChange = e => {
const { name, value } = e.target;
setValues({
...values,
[name]: value
});
};
const handleSubmit = e => {
e.preventDefault();
setErrors(validate(values));
setIsSubmitting(true);
};
useEffect(
() => {
if (Object.keys(errors).length === 0 && isSubmitting) {
callback();
}
},
[errors]
);
return { handleChange, handleSubmit, values, errors };
};
export default useForm;
export default function validateInfo(values) {
let errors = {};
if (!values.username.trim()) {
errors.username = 'Username required';
}
// else if (!/^[A-Za-z]+/.test(values.name.trim())) {
// errors.name = 'Enter a valid name';
// }
if (!values.email) {
errors.email = 'Email required';
} else if (!/\S+@\S+\.\S+/.test(values.email)) {
errors.email = 'Email address is invalid';
}
if (!values.password) {
errors.password = 'Password is required';
} else if (values.password.length < 6) {
errors.password = 'Password needs to be 6 characters or more';
}
if (!values.password2) {
errors.password2 = 'Password is required';
} else if (values.password2 !== values.password) {
errors.password2 = 'Passwords do not match';
}
return errors;
}
import React from 'react';
import './App.css';
import Form from './Form';
function App() {
return <Form />;
}
export default App;
@import url('https://fonts.googleapis.com/css2?family=PT+Sans&display=swap');
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: 'PT Sans', sans-serif;
}
import React from 'react';
import validate from './validateInfo';
import useForm from './useForm';
import './Form.css';
const FormSignup = ({ submitForm }) => {
const { handleChange, handleSubmit, values, errors } = useForm(
submitForm,
validate
);
return (
<div className='form-content-right'>
<form onSubmit={handleSubmit} className='form' noValidate>
<h1>
Get started with us today! Create your account by filling out the
information below.
</h1>
<div className='form-inputs'>
<label className='form-label'>Username</label>
<input
className='form-input'
type='text'
name='username'
placeholder='Enter your username'
value={values.username}
onChange={handleChange}
/>
{errors.username && <p>{errors.username}</p>}
</div>
<div className='form-inputs'>
<label className='form-label'>Email</label>
<input
className='form-input'
type='email'
name='email'
placeholder='Enter your email'
value={values.email}
onChange={handleChange}
/>
{errors.email && <p>{errors.email}</p>}
</div>
<div className='form-inputs'>
<label className='form-label'>Password</label>
<input
className='form-input'
type='password'
name='password'
placeholder='Enter your password'
value={values.password}
onChange={handleChange}
/>
{errors.password && <p>{errors.password}</p>}
</div>
<div className='form-inputs'>
<label className='form-label'>Confirm Password</label>
<input
className='form-input'
type='password'
name='password2'
placeholder='Confirm your password'
value={values.password2}
onChange={handleChange}
/>
{errors.password2 && <p>{errors.password2}</p>}
</div>
<button className='form-input-btn' type='submit'>
Sign up
</button>
<span className='form-input-login'>
Already have an account? Login <a href='#'>here</a>
</span>
</form>
</div>
);
};
export default FormSignup;
import React from 'react';
import useState from 'react';
import './Form.css';
import FormSignup from './FormSignup';
import FormSuccess from './FormSuccess';
const Form = () => {
const [isSubmitted, setIsSubmitted] = useState(false);
function submitForm() {
setIsSubmitted(true);
}
return (
<>
<div className='form-container'>
<span className='close-btn'>×</span>
<div className='form-content-left'>
<img className='form-img' src='img/img-2.svg' alt='spaceship' />
</div>
{!isSubmitted ? (
<FormSignup submitForm={submitForm} />
) : (
<FormSuccess />
)}
</div>
</>
);
};
export default Form;
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
.form-container {
margin: 100px auto;
width: 1000px;
box-shadow: 0 5px 8px 0 rgba(0, 0, 0, 0.2), 0 7px 20px 0 rgba(0, 0, 0, 0.2);
position: relative;
border-radius: 10px;
height: 600px;
display: grid;
grid-template-columns: 1fr 1fr;
}
.close-btn {
position: absolute;
top: 2%;
right: 3%;
font-size: 1.5rem;
z-index: 1;
color: #fff;
cursor: pointer;
}
.form-content-left {
background: linear-gradient(
90deg,
rgb(39, 176, 255) 0%,
rgb(0, 232, 236) 100%
);
border-radius: 10px 0 0 10px;
position: relative;
}
.form-img {
width: 80%;
height: 80%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.form-img-2 {
width: 60%;
height: 60%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.form-success {
text-align: center;
font-size: 24px;
margin-top: 80px;
color: #fff;
}
.form-content-right {
border-radius: 0 10px 10px 0;
position: relative;
background: linear-gradient(90deg, rgb(40, 40, 40) 0%, rgb(17, 17, 17) 100%);
}
.form {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 90%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.form h1 {
font-size: 1rem;
text-align: start;
width: 80%;
margin-bottom: 1rem;
color: #fff;
}
.form-inputs {
margin-bottom: 0.5rem;
width: 80%;
}
.form-inputs p {
font-size: 0.8rem;
margin-top: 0.5rem;
color: #f00e0e;
}
.form-label {
display: inline-block;
font-size: 0.8rem;
margin-bottom: 6px;
color: #fff;
}
.form-input {
display: block;
padding-left: 10px;
outline: none;
border-radius: 2px;
height: 40px;
width: 100%;
border: none;
}
.form-input::placeholder {
color: #595959;
font-size: 12px;
}
.form-input-btn {
width: 80%;
height: 50px;
margin-top: 10px;
border-radius: 2px;
background: linear-gradient(
90deg,
rgb(39, 176, 255) 0%,
rgb(0, 232, 236) 100%
);
outline: none;
border: none;
color: #fff;
font-size: 1rem;
}
.form-input-btn:hover {
cursor: pointer;
background: linear-gradient(
90deg,
rgb(39, 143, 255) 0%,
rgb(12, 99, 250) 100%
);
transition: all 0.4s ease-out;
}
.form-input-login {
font-size: 0.8rem;
margin-top: 10px;
color: #fff;
width: 80%;
text-align: center;
}
.form-input-login a {
text-decoration: none;
color: #27cdff;
font-weight: 600;
}