Javascript 如何正确包装JSX元素并根据选择显示JSON
我正在开发一个大学管理网站,可以用不同的语言显示React。到目前为止,我已经开发了如下的登录页面: 此时,我正试图用所选语言eu、ES、EN显示网站,但出现模块构建失败错误: 我真的不明白为什么会出现这个错误,因为我认为JSX/html标记包装正确。注意,我使用的是Babel,请参阅代码: Login.js 使用api: api.js 错误的真正原因是什么 根据React的选择,显示JSON数据的正确方式是什么Javascript 如何正确包装JSX元素并根据选择显示JSON,javascript,json,reactjs,jsx,babeljs,Javascript,Json,Reactjs,Jsx,Babeljs,我正在开发一个大学管理网站,可以用不同的语言显示React。到目前为止,我已经开发了如下的登录页面: 此时,我正试图用所选语言eu、ES、EN显示网站,但出现模块构建失败错误: 我真的不明白为什么会出现这个错误,因为我认为JSX/html标记包装正确。注意,我使用的是Babel,请参阅代码: Login.js 使用api: api.js 错误的真正原因是什么 根据React的选择,显示JSON数据的正确方式是什么 将渲染中返回的内容包装到标记中 这就像错误消息所说的:相邻的标记必须包装在[par
将渲染中返回的内容包装到标记中
这就像错误消息所说的:相邻的标记必须包装在[parent]标记中。函数必须返回单个DOM元素或片段 更深入地了解一下你在这里返回的内容 函数LoginForm{repos,selectedLanguage}{ //... 回来 {lang.login} }} //...
您可以将所有内容包装到另一个元素中,也可以使用或。错误就是因为这样
return (
<div className='row player-inputs'>
<input
type='text'
id='username'
className='input-light'
placeholder={lang.username}
autoComplete='off'
/>
</div>
<div className='row player-inputs'>
<input
type='password'
id='password'
className='input-light'
placeholder={lang.password}
autoComplete='off'
/>
</div>
<div className='row player-inputs'>
<button
className='btn dark-btn'
type='submit'
>
{lang.login}
</button>
</div>
)
此处出现错误:
return (
<div className='row player-inputs'>
<input
type='text'
id='username'
className='input-light'
placeholder={lang.username}
autoComplete='off'
/>
</div>
<div className='row player-inputs'>
<input
type='password'
id='password'
className='input-light'
placeholder={lang.password}
autoComplete='off'
/>
</div>
...
您应该将其包装为一个标签,如
例如:
return (
<div>
<div className='row player-inputs'>
<input
type='text'
id='username'
className='input-light'
placeholder={lang.username}
autoComplete='off'
/>
</div>
<div className='row player-inputs'>
<input
type='password'
id='password'
className='input-light'
placeholder={lang.password}
autoComplete='off'
/>
</div>
<div className='row player-inputs'>
<button
className='btn dark-btn'
type='submit'
>
{lang.login}
</button>
</div>
</div>
)
错误的真正原因是什么
组件正在返回多个JSX元素。但不包含在单个父JSX元素中。因此,按照错误提示使用
return (
<> // shorthand syntax of React.Fragment
{children}
</>
);
根据React的选择,显示JSON数据的正确方式是什么
据我所知,您正确地跟踪了React的状态
状态即selectedLanguage存储在父组件中并传递给 我使您的代码按预期工作,请运行并让我知道您的反馈 变化 包装的元素返回React.Fragment getSelectedLang引入了新方法来处理selectedLang,而不是在LoginForm中 LoginForm已更改为类内的成员 直接注入响应,而不是请求获取数据 见守则-
我自己设法解决了这个问题。我没有正确地传递道具,因为我试图在LoginForm函数中接收2个道具,而我只传递了1个,并且没有检查repos是否为null:
<LoginForm repos={repos, selectedLanguage} />
解决方案:
{repos && <LoginForm repos={repos} selectedLanguage={selectedLanguage} />}
我设法解决了这个问题,问了另一个问题:
然后我在LoginForm函数中开发了一个逻辑,以显示所选的语言
完整解决方案:
谢谢你的回答。我认为你的答案是正确的,但是,我认为最好像其他答案所建议的那样用标签来包装它。是的,你是对的。这确实是比我的解决方案更好的解决方案,因为它不需要为回答我的第一个问题添加多余的感谢。关于第二个问题的答案,如果我错了请纠正我,但我认为映射对我想做的不起作用,因为我需要通过所选语言和基于选定语言JSON项目。谢谢您的回答,但是,即使您的解决方案可能起作用,我也不认为它是有效的。当您将整个代码解构并将JSON数据放在一个对象中时。请看我的答案,因为我已经设法开发出一个解决方案,在保持代码良好的同时满足我的要求。谢谢你的反馈谢谢你的评论,但问题已经解决了。
return (
<div className='row player-inputs'>
<input
type='text'
id='username'
className='input-light'
placeholder={lang.username}
autoComplete='off'
/>
</div>
<div className='row player-inputs'>
<input
type='password'
id='password'
className='input-light'
placeholder={lang.password}
autoComplete='off'
/>
</div>
...
return (
<div>
<div className='row player-inputs'>
<input
type='text'
id='username'
className='input-light'
placeholder={lang.username}
autoComplete='off'
/>
</div>
<div className='row player-inputs'>
<input
type='password'
id='password'
className='input-light'
placeholder={lang.password}
autoComplete='off'
/>
</div>
<div className='row player-inputs'>
<button
className='btn dark-btn'
type='submit'
>
{lang.login}
</button>
</div>
</div>
)
return (
<> // shorthand syntax of React.Fragment
{children}
</>
);
import ReactDOM from "react-dom";
import React from "react";
import PropTypes from "prop-types";
//import { fetchPopularRepos } from '../utils/api'
function LanguagesNav({ selected, onUpdateLanguage }) {
const languages = ["EU", "ES", "EN"];
return (
<div>
<h1 className="center-text header-lg">GAUR 2.0</h1>
<ul className="flex-center">
{languages.map(language => (
<li key={language}>
<button
className="btn-clear nav-link"
style={
language === selected ? { color: "rgb(187, 46, 31)" } : null
}
onClick={() => onUpdateLanguage(language)}
>
{language}
</button>
</li>
))}
</ul>
</div>
);
}
LanguagesNav.propTypes = {
selected: PropTypes.string.isRequired,
onUpdateLanguage: PropTypes.func.isRequired
};
export default class Login extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedLanguage: "EU",
repos: null,
error: null
};
this.updateLanguage = this.updateLanguage.bind(this);
this.isLoading = this.isLoading.bind(this);
this.LoginForm = this.LoginForm.bind(this);
}
getSelectedLang = (repos, selectedLanguage) => {
console.log('repos', repos);
console.log('selectedLanguage', selectedLanguage);
var lang = "";
switch (selectedLanguage) {
case "EU":
selectedLanguage = "EU";
lang = repos && repos[0];
break;
case "ES":
selectedLanguage = "ES";
lang = repos && repos[1];
break;
case "EN":
selectedLanguage = "EN";
lang = repos && repos[2];
break;
default:
break;
}
return (
<React.Fragment>
<div className="row player-inputs">
<input
type="text"
id="username"
className="input-light"
placeholder={lang &&lang.terms.username}
autoComplete="off"
/>
</div>
<div className="row player-inputs">
<input
type="password"
id="password"
className="input-light"
placeholder={lang &&lang.terms.password}
autoComplete="off"
/>
</div>
<div className="row player-inputs">
<button className="btn dark-btn" type="submit">
{lang && lang.terms.login}
</button>
</div>
</React.Fragment>
);
}
LoginForm = (repos, selectedLanguage) => {
// let { repos, selectedLanguage } = data;
return (
<form className="column player">
{this.getSelectedLang(repos, selectedLanguage)}
</form>
);
}
componentDidMount() {
this.updateLanguage(this.state.selectedLanguage);
// console.log("heoocds");
}
updateLanguage = (selectedLanguage) => {
//console.log(selectedLanguage);
// console.log("heoocds");
let obj =
[{
language: "EU",
terms: {
username: "Erabiltzailea",
password: "Pasahitza",
welcome: "Sartu GAUR 2.0ra",
login: "Sartu"
}
},
{
language: "ES",
terms: {
username: "Usuario",
password: "Contraseña",
welcome: "Entra a GAUR 2.0",
login: "Entrar"
}
},
{
language: "EN",
terms: {
password: "Password",
username: "Username",
welcome: "Log into GAUR 2.0",
login: "Log in"
}
} ]
this.setState({
selectedLanguage,
error: null,
repos: obj
});
};
// fetchPopularRepos(selectedLanguage)
// .then((repos) => this.setState({
// repos,
// error: null,
// }))
// .catch(() => {
// console.warn('Error fetching repos: ', error)
// this.setState({
// error: 'There was an error fetching the repositories.'
// })
// })
isLoading = () => {
return this.state.repos === null && this.state.error === null;
}
render() {
const { selectedLanguage, repos, error } = this.state;
// console.log(repos);
// console.log(selectedLanguage)
return (
<React.Fragment>
<LanguagesNav
selected={selectedLanguage}
onUpdateLanguage={this.updateLanguage}
/>
{this.isLoading() && <p>LOADING...</p>}
{error && <p>{error}</p>}
{this.LoginForm(repos, selectedLanguage)}
</React.Fragment>
);
}
}
ReactDOM.render(<Login />, document.getElementById("root"));
<LoginForm repos={repos, selectedLanguage} />
{repos && <LoginForm repos={repos} selectedLanguage={selectedLanguage} />}
import React from 'react'
import PropTypes from 'prop-types'
import { fetchPopularRepos } from '../utils/api'
function LanguagesNav ({ selected, onUpdateLanguage}) {
const languages = ['EU', 'ES', 'EN']
return (
<div >
<h1 className='center-text header-lg'>
GAUR 2.0
</h1>
<ul className='flex-center'>
{languages.map((language) => (
<li key={language}>
<button
className='btn-clear nav-link'
style={language === selected ? { color: 'rgb(187, 46, 31)' } : null }
onClick={() => onUpdateLanguage(language)}>
{language}
</button>
</li>
))}
</ul>
</div>
)
}
LanguagesNav.propTypes = {
selected: PropTypes.string.isRequired,
onUpdateLanguage: PropTypes.func.isRequired
}
function LoginForm ({ repos, selectedLanguage }) {
var lang = {}
switch (selectedLanguage) {
case "EU":
selectedLanguage = "EU";
lang = repos[0].terms;
break;
case "ES":
selectedLanguage = "ES";
lang = repos[1].terms;
break;
case "EN":
selectedLanguage = "EN";
lang = repos[2].terms;
break;
}
return (
<form className='column player'>
<div className='row player-inputs'>
<input
type='text'
id='username'
className='input-light'
placeholder={lang.username}
autoComplete='off'
/>
</div>
<div className='row player-inputs'>
<input
type='password'
id='password'
className='input-light'
placeholder={lang.password}
autoComplete='off'
/>
</div>
<div className='row player-inputs'>
<button
className='btn dark-btn'
type='submit'
>
{lang.login}
</button>
</div>
</form>
)
}
LoginForm.propTypes = {
repos: PropTypes.array.isRequired
}
export default class Login extends React.Component {
constructor(props) {
super(props)
this.state = {
selectedLanguage: 'EU',
repos: null,
error: null
}
this.updateLanguage = this.updateLanguage.bind(this)
this.isLoading = this.isLoading.bind(this)
}
componentDidMount () {
this.updateLanguage(this.state.selectedLanguage)
}
updateLanguage (selectedLanguage) {
this.setState({
selectedLanguage,
error: null,
repos: null
})
fetchPopularRepos(selectedLanguage)
.then((repos) => this.setState({
repos,
error: null,
}))
.catch(() => {
console.warn('Error fetching repos: ', error)
this.setState({
error: 'There was an error fetching the repositories.'
})
})
}
isLoading() {
return this.state.repos === null && this.state.error === null
}
render() {
const { selectedLanguage, repos, error } = this.state
return (
<React.Fragment>
<LanguagesNav
selected={selectedLanguage}
onUpdateLanguage={this.updateLanguage}
/>
{this.isLoading() && <p>LOADING...</p>}
{error && <p>{error}</p>}
{repos && <LoginForm repos={repos} selectedLanguage={selectedLanguage} />}
</React.Fragment>
)
}
}