首先,我在此处查看了许多与此类似的问题,因此找不到解决方案。基本上在App.js中,我有两个按钮可以在英语和西班牙语之间切换this.state.language
。当我对语言状态进行硬编码时,它将起作用。 (我通过JSON文件获取语言数据)。
但是,现在,当我尝试使用两个按钮时,状态会更改(通过控制台日志验证),但页面上的语言不会更新。在下面的页面上,我有一个if语句来检测语言状态,然后从中选择JSON文件中的位置来获取数据。请有人可以向我解释为什么这行不通吗?
App.js
class App extends Component {
constructor(){
super();
this.state = {
sideNav: '',
language: ''
}
this.langEn = this.langEn.bind(this);
this.langEs = this.langEs.bind(this);
}
langEn() {
this.setState({language: 'en'});
console.log(this.state);
}
langEs() {
this.setState({language: 'es'});
console.log(this.state);
}
render() {
const mouseEnter = e => {
this.setState({sideNav: "sideNav sidenav---sidenav---_2tBP sidenav---expanded---1KdUL"});
}
const mouseLeave = e => {
this.setState({sideNav: "sidenav---sidenav---_2tBP sidenav---collapsed---LQDEv"});
}
return (
<div className="App container">
<div>
<SideNav
onMouseEnter={mouseEnter}
onMouseLeave={mouseLeave}
className={this.state.sideNav}
onSelect={(selected) => {
// Add your code here
}}
>
<SideNav.Nav defaultSelected="home">
<NavItem eventKey="home">
<NavIcon>
<Link to="/"><img src={Dash}/></Link>
</NavIcon>
<NavText>
<Link to="/">Dashboard</Link>
</NavText>
</NavItem>
<NavItem eventKey="sites">
<NavIcon>
<Link to="/sites"><img src={Site} /></Link>
</NavIcon>
<NavText>
<Link to="/sites">Sites</Link>
</NavText>
</NavItem>
<NavItem eventKey="tours">
<NavIcon>
<Link to="/tours"><img src={Tour}/></Link>
</NavIcon>
<NavText>
<Link to="/tours">Tours</Link>
</NavText>
</NavItem>
<NavItem eventKey="media">
<NavIcon>
<Link to="/media"><img src={Media}/> </Link>
</NavIcon>
<NavText>
<Link to="/media">Media</Link>
</NavText>
</NavItem>
<NavItem eventKey="newSite">
<NavIcon>
<Link to="/newSite/details"><img src={NewSite} /></Link>
</NavIcon>
<NavText>
<Link to="/newSite/details">Add new Site</Link>
</NavText>
</NavItem>
<NavItem eventKey="language">
<NavIcon>
<Link to="/language"><img src={Lang} /></Link>
</NavIcon>
<NavText>
<Link to="/language">Language</Link>
</NavText>
</NavItem>
<NavItem eventKey="profile">
<NavIcon>
<Link to="/profile"><img src={Profile} /></Link>
</NavIcon>
<NavText>
<Link to="/profile">Profile</Link>
</NavText>
</NavItem>
</SideNav.Nav>
<button onClick={this.langEn}>EN</button>
<button onClick={this.langEs}>ES</button>
</SideNav>
</div>
<Routes childProps={this.state} />
</div>
);
}
}
export default App;
我要翻译的页面:
import React, { Component } from 'react';
import { Col, Button, Form, FormGroup, Label, Input } from 'reactstrap';
import {withRouter} from 'react-router-dom';
import './NewForm.css';
import data from '../data.json';
class NewFormDetails extends Component {
constructor(props) {
super(props);
this.state = {
language: '',
siteName: '',
counties: '',
siteAddress: '',
siteEmail: '',
siteNumber: '',
siteCat: '',
openTimes: '',
fees: '',
access: '',
gps: '',
w3w: '',
txtHeader: '',
txtContent: ''
};
}
validateForm() {
if (this.state.siteName != '' &&
this.state.siteAddress != '' &&
this.state.siteEmail != '' &&
this.state.siteNumber != '' &&
this.state.openTimes != '' &&
this.state.fees != '' &&
this.state.access != '' &&
this.state.gps != '' &&
this.state.w3w != '' &&
this.state.txtHeader != '' &&
this.state.txtContent != '') {
return true;
} else {
return false;
}
}
handleChange = e => {
this.setState({ ...this.state, [e.target.name]: e.target.value });
console.log(this.state);
}
handleSubmit = event => {
event.preventDefault();
console.log(this.state);
this.props.history.push('/newSite/tours');
}
render() {
this.setState({language: this.props.language});
let jsonLang;
if (this.state.language == 'en') {
jsonLang = data.en;
} else if (this.state.language == 'es') {
jsonLang = data.es;
} else {
jsonLang = data.en;
}
this.placeholders = jsonLang.placeholders;
this.counties = jsonLang.counties;
this.categories = jsonLang.categories;
console.log(this.state.language)
return (
<Form onSubmit={this.handleSubmit} className="form">
{/* General Information */}
<FormGroup row>
<Col sm={6}>
<Input type="text" onChange={this.handleChange} name="siteName" id="siteName" placeholder={this.placeholders.siteName}/>
</Col>
<Col sm={6}>
<Input className="form-control" type="select" id="counties" onChange={this.handleChange}>
<option className="selectDefault" disabled value={this.placeholders.siteCounties} selected>{this.placeholders.siteCounty}</option>
{ this.counties.map(c => (<option key={c.value} value={c.value}>{c.display}</option>))}
</Input>
</Col>
</FormGroup>
<FormGroup row>
<Col sm={12}>
<Input type="textarea" onChange={this.handleChange} name="siteAddress" placeholder={this.placeholders.siteAdd} id="siteAddress" />
</Col>
</FormGroup>
<FormGroup row>
<Col sm={6}>
<Input type="email" name="siteEmail" onChange={this.handleChange} id="siteEmail" placeholder={this.placeholders.email} />
</Col>
<Col sm={6}>
<Input type="tel" name="siteNumber" onChange={this.handleChange} id="siteNumber" placeholder={this.placeholders.number}/>
</Col>
</FormGroup>
<FormGroup row>
<Col sm={6}>
<Input type="select" name="siteCat" onChange={this.handleChange} id="siteCat" multiple placeholder={this.placeholders.categories}>
<option className="selectDefault" disabled selected>{this.placeholders.categories}</option>
{ this.categories.map(c => (<option key={c.value} value={c.value}>{c.display}</option>))}
</Input>
</Col>
<Col sm={6}>
<Input type="textarea" name="openTimes" onChange={this.handleChange} id="openTimes" placeholder={this.placeholders.times} />
</Col>
</FormGroup>
<FormGroup row>
<Col sm={6}>
<Input type="textarea" name="fees" onChange={this.handleChange} id="fees" placeholder={this.placeholders.fees}/>
</Col>
<Col sm={6}>
<Input type="text" name="access" onChange={this.handleChange} id="access" placeholder={this.placeholders.access} />
</Col>
</FormGroup>
<hr/>
{/* Location Information */}
<FormGroup row>
<Col sm={6}>
<Input type="text" name="gps" onChange={this.handleChange} id="gps" placeholder={this.placeholders.gps}/>
</Col>
<Col sm={6}>
<Input type="text" name="w3w" id="w3w" onChange={this.handleChange} placeholder={this.placeholders.w3w} />
</Col>
</FormGroup>
<hr/>
<FormGroup row>
<Col sm={12}>
<Input type="textarea" name="txtHeader" onChange={this.handleChange} id="txtHeader" placeholder={this.placeholders.textHeader} />
</Col>
</FormGroup>
<FormGroup row>
<Col sm={12}>
<Input type="textarea" name="txtContent" onChange={this.handleChange} id="txtContent" placeholder={this.placeholders.textContent} />
</Col>
</FormGroup>
<FormGroup check row>
<Col sm={{ size: 10, offset: 2 }}>
<Button disabled={!this.validateForm()} type="submit" className="btn-primary">Tours →</Button>
</Col>
</FormGroup>
</Form>
);
}
}
export default withRouter(NewFormDetails);
答案 0 :(得分:1)
问题在于App
从不使用this.state.language
并且不会将其传递给任何其他组件。
如果要将语言设置为App
级别,则至少有两个选择:
language
传递给需要状态的组件。#1的简要示例:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
language: "en"
};
this.langEn = this.langEn.bind(this);
this.langEs = this.langEs.bind(this);
}
langEs() {
this.setState({language: "es"});
}
langEn() {
this.setState({language: "en"});
}
render() {
const {language} = this.state;
return (
<div>
<button onClick={this.langEn}>English</button>
<button onClick={this.langEs}>Español</button>
<Thingy language={language} />
<Whatsit language={language} />
</div>
);
}
}
class Thingy extends React.Component {
render() {
const {language} = this.props;
return <div>Thingy's language is {language}</div>;
}
}
const Whatsit = props => (
<div>Whatsit's language is {props.language}</div>
);
ReactDOM.render(<App />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
第2个快速示例:
const LangContext = React.createContext("en");
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
language: "en"
};
this.langEn = this.langEn.bind(this);
this.langEs = this.langEs.bind(this);
}
langEs() {
this.setState({language: "es"});
}
langEn() {
this.setState({language: "en"});
}
render() {
const {language} = this.state;
return (
<LangContext.Provider value={language}>
<div>
<button onClick={this.langEn}>English</button>
<button onClick={this.langEs}>Español</button>
<Thingy />
<Whatsit />
</div>
</LangContext.Provider>
);
}
}
class Thingy extends React.Component {
static contextType = LangContext;
render() {
const language = this.context;
return <div>Thingy's language is {language}</div>;
}
}
class Whatsit extends React.Component {
static contextType = LangContext;
render() {
const language = this.context;
return <div>Whatsit's language is {language}</div>;
}
}
ReactDOM.render(<App />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
答案 1 :(得分:-1)
正如注释中已经提到的那样,您没有在this.state.language
的{{1}}方法中使用render()
。只有在新状态实际上对NewFormDetails
方法产生影响时,React才会重新渲染组件。
由于您只是在构造函数中使用它,因此react不会重新呈现您的组件。只需将if-else语句移至render方法,就可以了。
编辑:
您正在将render()
复制到组件状态,但是此后没有更改状态。 this.props.language
在外部发生了变化,但这些变化未反映在组件内部。您应该直接在this.props.language
方法内部访问this.props.lanugage
。
render()
还是您有理由将其复制到州?
答案 2 :(得分:-1)
我注意到您从道具中获取了语言,并在NewFormDetails的构造函数中设置了转换后的字符串。当您单击按钮以更改语言时,NewFormDetails只是更新了,不需要执行构造函数,因此字符串是旧字符串。 我认为您可以从渲染功能中的道具获取语言,并在渲染功能中设置字符串。