父组件更改状态后,子组件不会重新呈现

时间:2019-08-04 11:08:15

标签: reactjs

我是React的初学者,遇到了一些问题。 我有两个组成部分。一个是父代,它将其状态传递给子代组件。另一个是接收通过状态并将其用作道具的孩子。 我想做的是,当我单击父组件(Detailsrch)中的列表元素时,其状态更改并影响到子组件(Btnfunctionlocal),因此它将重新呈现。 这是用于从父组件中选择地址,并从子组件中选择详细地址。

我尝试使用this.forceupdate和getderivedstatefromprops,但这似乎使工作更加困难。我试图把父母的状态变成孩子的状态。我使用console.log查看发生了什么,但是console.log打印正确的值,但浏览器中的值与从父组件中选择的第一个值没有变化。




这是父组件

import React, { Component } from 'react';
import { Jumbotron } from 'react-bootstrap';
import { Btnfunctionlocal } from './Locals/Btnfunction';
import './Detailsrch.css';

class Detailsrch extends Component {
    constructor(props) {
        super(props);
        this.state = {
            local: '',
            localdetail: ''
        }
        this.whichlocal = (e) => {
            console.dir(e.target);
            // Here is the code that changes parent component's state
            this.setState({
                local: e.target.innerText
            })
            // From here to
            let selector = document.getElementsByClassName('locals');
            let i = 0;
            while (selector[i]) {
                selector[i].classList.remove('localclick');
                i++;
            }
            if (e.target.className === 'localtext') {
                e.target.parentElement.classList.add('localclick');
            } else {
                e.target.classList.add('localclick');
            }
            // here is for change css after click
        }
    }
    render() {
        console.log(this.state);
        return (
            <Jumbotron className='searchjumbo'>
                <p>Address</p>
                <ul>
                    {['All', 'Seoul', 'Incheon', 'Busan'].map((value, index) => {
                        return <li className='locals' onClick={this.whichlocal} name={'localdiv' + index} key={index}><span className='localtext' name={'localdiv' + index}>{value}</span></li>
                    })}
                </ul>
                {this.state.local?<Btnfunctionlocal local={this.state.local} />:''}
                <hr className='firsthr' />
            </Jumbotron>
        );
    }
};

export default Detailsrch;



这是子组件

export class Btnfunctionlocal extends Component {
    constructor(props){
        super(props)
        const local = {
            Seoul: ['강남구', '강동구', '강북구', '강서구', '관악구', '광진구', '구로구', '금천구', '노원구', '도봉구', '동대문구', '동작구', '마포구', '서대문구', '서초구', '성동구', '성북구', '송파구', '양천구', '영등포구', '용산구', '은평구', '종로구', '중구', '중랑구'],
            Incheon: ['강화군', '계양구', '미추홀구', '남동구', '동구', '부평구', '서구', '연수구', '옹진구', '중구'],
            Busan: ['강서구', '금정구', '기장군', '남구', '동구', '동래구', '부산진구', '북구', '사상구', '사하구', '서구', '수영구', '연제구', '영도구', '중구', '해운대구']
        }
        this.locallist = local[this.props.local].slice();

    }
    render(){
        return(
            <div className='localdiv'>
            {this.locallist.map((value, index)=>{
                return <div className={"searchselector"} key={index}>{value}</div>
            })}
            </div>
        )
    }
}

我也尝试过

export class Btnfunctionlocal extends Component {
    constructor(props) {
        super(props)
        const local = {
            Seoul: ['강남구', '강동구', '강북구', '강서구', '관악구', '광진구', '구로구', '금천구', '노원구', '도봉구', '동대문구', '동작구', '마포구', '서대문구', '서초구', '성동구', '성북구', '송파구', '양천구', '영등포구', '용산구', '은평구', '종로구', '중구', '중랑구'],
            Incheon: ['강화군', '계양구', '미추홀구', '남동구', '동구', '부평구', '서구', '연수구', '옹진구', '중구'],
            Busan: ['강서구', '금정구', '기장군', '남구', '동구', '동래구', '부산진구', '북구', '사상구', '사하구', '서구', '수영구', '연제구', '영도구', '중구', '해운대구']
        }
        this.state = {
            local: []
        }
    }
    componentDidMount() {
        this.setState({
            local: local[this.props.local].slice()
        })
    }
    render() {
        return (
            <div className='localdiv'>
                {this.state.local.slice().map((value, index) => {
                    return <div className={"searchselector"} key={index}>{value}</div>
                })}
            </div>
        )
    }
}



我希望当我单击父级的list元素时,子级的元素会发生变化,但是除了第一次单击之外,其他都没有变化。

1 个答案:

答案 0 :(得分:1)

因此,有几件事我会改变。但首先要回答您的问题: 您可以将道具复制到子组件中安装时的本地状态,但是如果父道具更改,则不会更新状态。有一种方法可以使用componentDidUpdate进行修复:

componentDidUpdate(prevProps) {
    if(prevProps.local !== this.props.local) {
        this.setState({
             local: local[this.props.local].slice()
        })
    }        
}

这将侦听道具更改并更新您的本地状态,您可以在渲染方法中相应地访问该状态。另外,您可以在渲染方法期间直接使用父道具,并删除co​​mponentDidUpdate和componentDidMount,如下所示:

render() {
    return (
        <div className='localdiv'>
            {local[this.props.local].slice().map((value, index) => {
                return <div className={"searchselector"} key={index}>{value}</div>
            })}
        </div>
    )
}

此外,我完全不会使用document.getElementsByClassName并通过css样式的三元操作和js处理它。 最后,我将使用e.target.value访问更改的值,因为innerText可能与value不同。