我无法正确使用setState更改值

时间:2019-01-06 21:59:46

标签: javascript reactjs react-redux

我正在尝试使用setState更改组件状态(personId)中的值,并使用从render()内部获得的值(pid)。

此组件内部有三种方案。所有这些都是相同的场景,但是根据我从Axios的API调用中收到的内容进行了一些小的更改。

我更改componentDidMount内部的状态,我猜它在打开组件时运行一次,我还尝试过更改componentDidUpdate内部的状态,这会导致无限循环。

我还忽略了与该问题没有任何关系的代码段,只是为了使其更简洁。

class SearchPage extends React.Component {

    state = {
        personId: '',
        person_results: [],
    }

        componentDidMount(){
            //this.props.fetchPersonInfo(this.state.personId)
            let pid;
            if(this.props.results.length > 0){
                if (this.props.results[0].results[0].media_type === 'person'){
                    this.setState({person_results: this.props.results[0].results});
                    pid = this.state.person_results.id;
                } else if (this.props.results[0].results[1].media_type === 'person'){
                    this.setState({person_results: this.props.results[0].results})
                    pid = this.state.person_results.id;
                } else if (this.props.results[0].results[2].media_type === 'person'){
                    this.setState({person_results: this.props.results[0].results})
                    pid = this.state.person_results.id
                }
            }
            this.setState({
                personId: pid,
            })
        }


    render(){
            if (this.props.results.length > 0){
                if (this.props.results[0].results[0].media_type === 'person'){
                    console.log(this.props.results[0].results[0]);
                    console.log(this.state.person_results);
                    return (
                        <div className='.col-md-4 search-container'>
                                <div className='search-results-person'>
                                    <h5 className='search-title'>{this.state.person_results.name}</h5>
                                    <img className='search-image' src={`${img_url}${this.state.person_results.profile_path}`} alt={this.state.person_results.name} />
                                </div>
                        </div>
                    )
                } else if (this.props.results[0].results[1].media_type === 'person'){
                    console.log(this.state.person_results);
                    return (
                        <div className='.col-md-4 search-container'>
                                <div className='search-results-person'>
                                    <h5 className='search-title'>{this.state.person_results.name}</h5>
                                    <img className='search-image' src={`${img_url}${this.state.person_results.profile_path}`} alt={this.state.person_results.name} />
                                </div>
                        </div>
                    )
                } else if (this.props.results[0].results[2].media_type === 'person'){
                    console.log(this.state.person_results);
                    return (
                        <div className='.col-md-4 search-container'>
                                <div className='search-results-person'>
                                    <h5 className='search-title'>{this.state.person_results.name}</h5>
                                    <img className='search-image' src={`${img_url}${this.state.person_results.profile_path}`} alt={this.state.person_results.name} />
                                </div>
                        </div>
                    )
                }
            }
            return (
                <div className='container-fluid'>
                        <div className='row'>
                                {results}
                                {this.state.personId}
                                {this.state.person_results}
                        </div>
                </div>
            )
        }
    }

const mapStateToProps = (state) => {
    return {
        results: state.movTv.results,
        person: state.movTv.personInfo
    }
}

export default connect(mapStateToProps, { fetchPersonInfo })(SearchPage);

编辑:组件的更新代码。

2 个答案:

答案 0 :(得分:1)

您的变量pidperson_results的作用域是模块,即,它们的定义与SearchPage组件“处于同一级别”。在使用React时,仅在此级别定义const是个好主意(例如,您的图片网址)。现在,React无法听这些变量的更改,因此不会在这样的行上更新状态:

person_results = this.props.results[0].results[0];
pid = person_results.id;

如果您希望React在变量更改时更新组件,则应将这些变量定义为构造函数内的状态属性:

class SearchPage extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      person_results = /*...*/,
      pid: /*...*/
    }
  }

  /*...*/

}

,然后相应地重构代码。

答案 1 :(得分:1)

您应该将render函数中具有的所有逻辑上移到componentDidMount中,但是在返回jsx的地方,您将改为setState,以便您的状态代表您要呈现的内容。然后,您的render函数应该只包含jsx,它将呈现您在状态下(在componentDidMount中设置的数据)

请注意,最初看起来很奇怪,您会在组件“挂载”之后调用setState,但是react会在实际渲染之前执行setState中的任何componentDidMount调用

看起来像-

class SearchPage extends React.Component {

    state = {
        personId: '',
        person_results: []
    }

        componentDidMount(){
            let pid;
            if (this.props.results.length > 0){
                if (this.props.results[0].results[0].media_type === 'person'){
                    person_results = this.props.results[0].results[0];
                    pid = person_results.id;
                } else if (this.props.results[0].results[1].media_type === 'person'){
                    person_results = this.props.results[0].results[1];
                    pid = person_results.id;
                } else if (this.props.results[0].results[2].media_type === 'person'){
                    person_results = this.props.results[0].results[2];
                    pid = person_results.id;
                }
            }
            this.setState({
                personId: pid,
                person_results
            })
        }


    render(){

            return (
                <div className='container-fluid'>
                        <div className='row'>
                                {this.state.personId}
                                {this.state.person_results}
                        </div>
                </div>
            )
        }
    }

const mapStateToProps = (state) => {
    return {
        results: state.movTv.results,
        person: state.movTv.personInfo
    }
}

export default connect(mapStateToProps, { fetchPersonInfo })(SearchPage);

可以对其进行更多的重构,但可以让您了解从何处开始