anu icon indicating copy to clipboard operation
anu copied to clipboard

Error Boundary bug,与 React 表现不一致

Open xilixjd opened this issue 5 years ago • 2 comments

第一次点击第一个 click button 为正常 第二次点击第一个 click button 后,元素错位,且生命周期错误

let A = (props) => <div>{props.a}</div>
        class App extends React.Component {
            constructor(props) {
                super(props)
                this.state = {
                    aaa: 'aaa',
                    num: 0,
                    error: false,
                }
                this.inputRef = null
                this.inputRefFunc = (element) => {
                    this.inputRef = element
                }
            }
            change(a){
                this.setState({
                    aaa:a
                })
            }
            click1() {
                var equal = this.state.aaa === "aaa"
                if (equal) {
                    this.setState({
                        aaa: "bbb"
                    })
                } else {
                    this.setState({
                        aaa: "aaa"
                    })
                }
                this.setState({
                    num: this.state.num + 1
                })
                this.setState({
                    num: this.state.num + 1
                })
                var self = this
                this.inputRef.focus()
            }
            click2() {
                var equal = this.state.aaa === "aaa"
                if (equal) {
                    this.setState({
                        aaa: "bbb"
                    })
                } else {
                    this.setState({
                        aaa: "aaa"
                    })
                }
                this.setState({
                    num: this.state.num + 2
                })
            }
            callback = () => {
                this.setState({
                    num: this.state.num + 1
                })
            }
            componentWillMount() {
                console.log("App componentWillMount")
                this.setState({
                    num: this.state.num + 1
                })
            }
            componentDidMount() {
                console.log('App componentDidMount')
                this.setState({
                    num: this.state.num + 1
                })
                this.setState({
                    num: this.state.num + 1
                })
            }
            componentWillUpdate() {
                console.log('App componentWillUpdate')
            }
            componentWillReceiveProps(nextProps) {
                console.log("App componentWillReceiveProps")
            }
            componentDidUpdate(){
                console.log('App componentDidUpdate')
            }
            componentDidCatch(a, b) {
                console.log(a, b)
                console.log("App componentDidCatch")
                this.setState({ error: true })
            }
            componentWillUnmount(){
                console.log('App componentWillUnmount')
            }
            render() {
                return(
                    <div>
                        {this.state.error ? <h2>error</h2> : <h2>no error</h2>}
                        <h2>{this.state.num}</h2>
                        <Inner callback={this.callback} className={this.state.aaa} />
                        <button style={ this.state.aaa === 'aaa' ? {} : {fontSize: "50px"}} onClick={() => this.click1()}>click</button>
                        <input ref={this.inputRefFunc}/>
                        {<A a={1}/>}
                    </div>
                )
             
            }
        }

        class Inner extends React.Component{
             constructor(props){
                super(props)
                this.state = {
                    innerP: "init",
                    num: 0
                }
            }
            componentWillMount(){
                console.log('Inner componentWillMount')
                this.setState({
                    num: this.state.num + 1,
                })
            }
            componentDidMount(){
                console.log('Inner componentDidMount')
                this.setState({
                    num: this.state.num + 1,
                })
                this.props.callback("bbb")
            }
            componentWillUpdate(){
                console.log('Inner componentWillUpdate')
            }
            componentDidUpdate(){
                console.log('Inner componentDidUpdate')
            }
            componentWillUnmount(){
                console.log('Inner componentWillUnmount')
            }
            componentWillReceiveProps(nextProps) {
                console.log("Inner componentWillReceiveProps")
                // this.props.changeAppState("inner change")
                this.setState({
                    innerP: "change",
                    num: this.state.num + 1
                })
            }
            click1() {
                this.props.callback()
            }
            render() {
                if (this.state.num === 3) {
                    throw new Error("error")
                }
                return (
                    <div className={this.props.className}>
                        <p>xxx{111}</p><p>{this.state.num}</p>
                        <button onClick={() => this.click1()}>click</button>
                    </div> 
                )
            }
        }

xilixjd avatar Dec 07 '18 07:12 xilixjd

以后有时间修修

RubyLouvre avatar Dec 07 '18 14:12 RubyLouvre

接着发个 bug 现在 Inner 组件里有个 Inner2 组件,点击第二个 click 按钮 第一个问题是点击后 Inner 组件里的 div 的 className 消失 第二个问题是 第三次点击后,Inner2 组件的 state.num 会增加,react 中不会

let A = (props) => <div>{props.a}</div>
        class App extends React.Component {
            constructor(props) {
                super(props)
                this.state = {
                    aaa: 'aaa',
                    num: 0,
                    error: false,
                }
                this.inputRef = null
                this.inputRefFunc = (element) => {
                    this.inputRef = element
                }
            }
            change(a){
                this.setState({
                    aaa:a
                })
            }
            click1() {
                var equal = this.state.aaa === "aaa"
                if (equal) {
                    this.setState({
                        aaa: "bbb"
                    })
                } else {
                    this.setState({
                        aaa: "aaa"
                    })
                }
                this.setState({
                    num: this.state.num + 1
                })
                this.setState({
                    num: this.state.num + 1
                })
                var self = this
                setTimeout(function() {
                    self.setState({
                        num: self.state.num + 1
                    })
                    // self.setState({
                    //     num: self.state.num + 1
                    // })
                }, 0)
                this.inputRef.focus()
            }
            click2() {
                var equal = this.state.aaa === "aaa"
                if (equal) {
                    this.setState({
                        aaa: "bbb"
                    })
                } else {
                    this.setState({
                        aaa: "aaa"
                    })
                }
                this.setState({
                    num: this.state.num + 2
                })
            }
            callback = () => {
                this.setState({
                    num: this.state.num + 1
                })
            }
            componentWillMount() {
                console.log("App componentWillMount")
                this.setState({
                    num: this.state.num + 1
                })
            }
            componentDidMount() {
                console.log('App componentDidMount')
                this.setState({
                    num: this.state.num + 1
                })
                this.setState({
                    num: this.state.num + 1
                })
            }
            // shouldComponentUpdate() {
            //     console.log("App shouldComponentUpdate")
            //     return false
            // }
            componentWillUpdate() {
                console.log('App componentWillUpdate')
            }
            componentWillReceiveProps(nextProps) {
                console.log("App componentWillReceiveProps")
            }
            componentDidUpdate(){
                console.log('App componentDidUpdate')
            }
            componentDidCatch(a, b) {
                console.log(a, b)
                console.log("App componentDidCatch")
                this.setState({ error: true })
            }
            componentWillUnmount(){
                console.log('App componentWillUnmount')
            }
            render() {
                return(
                    <div>
                        {this.state.error ? <h2>error</h2> : <h2>no error</h2>}
                        <h2>{this.state.num}</h2>
                        {this.state.aaa === 'aaa' ?  <Inner callback={this.callback} className={this.state.aaa} /> : <Inner2 className={this.state.aaa} />}
                        {/*<Inner callback={this.change.bind(this)} className={this.state.aaa}/>*/}
                        {/*<button onClick={() => this.click()}>click</button>*/}
                        <button style={ this.state.aaa === 'aaa' ? {} : {fontSize: "50px"}} onClick={() => this.click1()}>click</button>
                        <input ref={this.inputRefFunc}/>
                        {<A a={1}/>}
                    </div>
                )
            
            }
        }

        class Inner extends React.Component{
             constructor(props){
                super(props)
                this.state = {
                    innerP: "init",
                    num: 0,
                    error: false,
                }
            }
            componentWillMount(){
                console.log('Inner componentWillMount')
                this.setState({
                    num: this.state.num + 1,
                })
            }
            componentDidMount(){
                console.log('Inner componentDidMount')
                this.setState({
                    num: this.state.num + 1,
                })
                this.props.callback("bbb")
            }
            // shouldComponentUpdate() {
            //     console.log("Inner shouldComponentUpdate")
            //     return false
            // }
            componentWillUpdate(){
                console.log('Inner componentWillUpdate')
            }
            componentDidUpdate(){
                console.log('Inner componentDidUpdate')
            }
            componentWillUnmount(){
                console.log('Inner componentWillUnmount')
            }
            componentWillReceiveProps(nextProps) {
                console.log("Inner componentWillReceiveProps")
                // this.props.changeAppState("inner change")
                this.setState({
                    innerP: "change",
                    num: this.state.num + 1
                })
            }
            componentDidCatch(a, b) {
                console.log(a, b)
                console.log("Inner componentDidCatch")
                this.setState({ error: true })
            }
            click1() {
                this.props.callback()
            }
            render() {
                console.log(this.props.className)
                if (this.state.num === 3) {
                    throw new Error("error")
                }
                return (
                    <div className={this.props.className}>
                        {this.state.error ? <h2>Inner error</h2> : <h2>no Inner error</h2>}
                        <p>xxx{111}</p><p>{this.state.num}</p>
                        <button onClick={() => this.click1()}>click</button>
                        {<Inner2/>}
                    </div> 
                )
            }
        }

        class Inner2 extends React.Component{
            constructor(props){
                super(props)
                this.state = {
                    innerP: "init",
                    num: 0,
                }
            }
            componentWillMount(){
                console.log('Inner2 componentWillMount')
            }
            componentDidMount(){
                console.log('Inner2 componentDidMount')
                // this.setState({
                //     num: this.state.num + 1
                // })
            }
            componentWillUpdate(){
                console.log('Inner2 componentWillUpdate')
            }
            componentWillUnmount(){
                console.log('Inner2 componentWillUnmount')
            }
            componentWillReceiveProps(nextProps) {
                console.log("Inner2 componentWillReceiveProps")
                // this.setState({
                //     innerP: "change",
                // })
            }
            click1() {
                this.setState({
                    num: this.state.num + 1
                })
            }
            render() {
                if (this.state.num === 1) {
                    throw new Error("error")
                }
                return  <section className={this.props.className}><button onClick={() => this.click1()}>click</button><p>yyy</p><p>{this.state.innerP}</p><p>{this.state.num}</p></section>
            }

        }

xilixjd avatar Dec 12 '18 02:12 xilixjd