我试图了解如何使用道具或状态识别页面加载时的选定选项。我了解到React在value
标签上使用了defaultValue
或<select>
来为受控状态建立selected
的值,并且我知道不受控制的状态更灵活,但不是推荐的。在当前代码中,我正在尝试设置受控状态值,但是有两个问题使设置不正确。
1)我有一个属性,该属性的值应定义页面加载时最初选择的值,但是我知道我无法将其设置为状态值,因此它不适合受控环境设置。
2)当我将prop设置为value
时,我看到了页面加载时选择的值,但是我无法从下拉列表中选择其他选项。它没有改变,这使我相信,如果我使用的是受控环境,则需要使用状态。
根据以上信息,最佳解决方案是什么?我也很好奇,如果我切换到不受控制的设置会如何解决。根据我的信息会更好吗?任何帮助将不胜感激。
代码(请注意,由于在这种情况下使用了prop,因此我并未使用该状态,但是以前使用和显示该状态是为了可视化所尝试的两种方法)
import React from 'react';
export default class CategoryFilter extends React.Component {
constructor(props) {
super(props);
this.state = {value: ''};
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
console.log(this.state.value)
}
render() {
console.log("CategoryFilter");
console.log(this.props);
console.log(this.state.value);
return (
<div className="col-md-2 annotation-filter-section">
<p>Category:</p>
<select name="category" className="form-control annotation-filter-category" value={this.props.categoryQuery} onChange={this.handleChange}>
<option value=""></option>
{
this.props.category.map(
(category) => {
return ( <option key={category.categoryIdHash} value={category.categoryIdHash}>{category.categoryName}</option> )
}
)
}
</select>
</div>
);
}
}
代码一级升级:
export default class SearchForm extends React.Component {
render() {
return (
<CatgoryFilter category={this.props.category} categoryQuery={this.props.categoryQuery} />
)
}
}
父组件:
export default class FeedContainer extends React.Component{
constructor(props, context) {
super(props, context);
this.state = this.context.data || window.__INITIAL_STATE__;
}
fetchList() {
...
fetch(`${API_ROOT}` + '/api' + window.location.search, { compress: false })
.then(res => {
return res.json();
})
.then(data => {
console.log(data);
this.setState({
category: data.category,
categoryQuery: data.categoryQuery,
});
})
}
componentDidMount() {
this.fetchList();
}
render() {
return (
<SearchForm category={this.state.category} categoryQuery={this.state.categoryQuery} />
)
}
}
答案 0 :(得分:2)
如果要传递初始值,然后让组件处理自己的状态,这是一种方法:
import React, { Component } from 'react';
import { render } from 'react-dom';
class App extends Component {
constructor(props) {
super(props);
this.state = {
value: props.initialValue,
}
}
handleChange = (e) => {
const { value } = e.target;
this.setState({ value });
}
render() {
const { value } = this.state;
return (
<React.Fragment>
<input
onChange={this.handleChange}
value={value} />
</React.Fragment>
);
}
}
render(<App initialValue="Hello"/>, document.getElementById('root'));
实时示例here。
如果有必要,您可以提升状态并传递处理程序:
import React, { Component } from 'react';
import { render } from 'react-dom';
const Child = ({ value, handleChange }) => (
<input value={value} onChange={handleChange} />
)
class App extends Component {
constructor(props) {
super(props);
this.state = {
value: props.initialValue,
}
}
handleChange = (e) => {
const { value } = e.target;
this.setState({ value });
}
render() {
const { value } = this.state;
return (
<Child handleChange={this.handleChange} value={value} />
);
}
}
render(<App initialValue="Hello" />, document.getElementById('root'));
实时示例here。
答案 1 :(得分:1)
由于您是从获取请求中获取categoryQuery
的,因此您可能无法获取组件安装时间的值,因此需要使用componentWillReceiveProps生命周期方法,如下所示
import React from 'react';
import isEqual from 'lodash/isEqual';
export default class CategoryFilter extends React.Component {
constructor(props) {
super(props);
this.state = { value: '' };
this.handleChange = this.handleChange.bind(this);
}
componenetDidMount() {
this.setState({value:this.props.categoryQuery})
}
componentWillReceiveProps(nextProps) {
if (!isEqual(this.props, nextProps)) {
this.setState({ value: nextProps.categoryQuery })
}
}
handleChange(event) {
this.setState({ value: event.target.value });
console.log(this.state.value)
}
render() {
console.log("CategoryFilter");
console.log(this.props);
console.log(this.state.value);
return (
<div className="col-md-2 annotation-filter-section">
<p>Category:</p>
<select name="category" className="form-control annotation-filter-category" value={this.props.categoryQuery} onChange={this.handleChange}>
<option value=""></option>
{
this.props.category.map(
(category) => {
return (<option key={category.categoryIdHash} value={category.categoryIdHash}>{category.categoryName}</option>)
}
)
}
</select>
</div>
);
}
}
您可以使用lodash中的isEqual
来比较道具。您需要将nextProps和this.props进行比较,因为props发生任何更改(导致状态更改)时都会触发componentWillReceiveProps生命周期方法。将会导致无限的重新渲染。最好使用componentDidUpdate,因为不赞成componentWillReceiveProps。