代码之家  ›  专栏  ›  技术社区  ›  smellerbee

复杂条件呈现的反应方式是什么?

  •  3
  • smellerbee  · 技术社区  · 7 年前

    问题

    组件的条件呈现有问题。据我所见,有两种方法可以做到这一点。第一种方法很难看,因为当我必须处理多个条件时会变得很困难。第二种方法是明确的,但是它将组件本身添加到状态中,并且使用状态值进行进一步的计算是困难的。例如,检查错误的消息值。

    我已经给出了以下两种方法。请告诉我哪个更好。还有比这两种方法都好的方法吗?

    应用

    这是一个简单的应用程序,根据第一种方法中“err”属性的状态和第二种方法中comp属性的内容呈现“main”组件或“err”组件。

    最初渲染主组件。err属性在2秒后更新为某个值,这将触发重新提交。此时,我要呈现err组件。

    真正的应用程序是我在componentdidmount上有一个外部api调用,它可以失败,也可以成功。我必须根据结果显示不同的组件。更新多个状态值会稍微复杂一些。为了演示,我简化了下面的问题。

    两种类型的常见步骤

    npx create-react-app react-oop
    

    组件/err.js

    import React,{Component} from 'react'
    
    class Err extends Component {
        render(){
            return(
                <div>
                    Error Component
                </div>
                )
        }
    }
    
    export default Err
    

    组件/main.js

    import React, {Component} from 'react'
    
    class Main extends Component {
        render(){
            return( 
                <div>
                    Main Component
                </div>
            )
        }
    }
    
    export default Main
    

    第一种方法

    App.JS

    import React, { Component } from 'react';
    import logo from './logo.svg';
    import './App.css';
    import Err from './components/Err'
    import Main from './components/Main'
    
    class App extends Component {
    
      constructor(props){
        super(props)
        this.state = {
          err: null
        }
      this.setError = this.setError.bind(this)
      }
    
      setError(){
        return(
          this.setState(() => {
            return({
              err: 'Error'
            })
          })
        )
      }
    
      componentDidMount(){
        setTimeout(this.setError, 2000)
      }
    
      render() {
        return (
          <div className="App">
           { 
             this.state.err ? <Err /> : <Main />
           }
          </div>
        );
      }
    }
    
    export default App;
    

    第二种方法

    App.JS

    import React, { Component } from 'react';
    import logo from './logo.svg';
    import './App.css';
    import Err from './components/Err'
    import Main from './components/Main'
    
    class App extends Component {
    
      constructor(props){
        super(props)
        this.state = {
          comp: <Main />
        }
      this.setError = this.setError.bind(this)
      }
    
      setError(){
        return(
          this.setState(() => {
            return({
              comp: <Err />
            })
          })
        )
      }
    
      componentDidMount(){
        setTimeout(this.setError, 2000)
      }
    
      render() {
        return (
          <div className="App">
           {this.state.comp}
          </div>
        );
      }
    }
    
    export default App;
    
    2 回复  |  直到 7 年前
        1
  •  1
  •   RaphaMex    7 年前

    我绝对推荐第一种方法。在组件的状态中存储数据(json),而不是视图(jsx)。

    事实上,有第三种方法可以充分利用这两种方法:

    在呈现之前,使用jsx变量编辑视图(使用您的逻辑)

    import React, { Component } from 'react';
    import logo from './logo.svg';
    import './App.css';
    import Err from './components/Err';
    import Main from './components/Main';
    
    class App extends Component {
    
        constructor(props){
            super(props);
            this.state = {
                err: null
            };
        }
    
        // This way of writing functions saves you the binding
        setError = () => this.setState({err: 'Error'})
    
        componentDidMount(){
            setTimeout(this.setError, 2000);
        }
    
        render() {
            let comp = <Main />;
            // Put your logic here so your returned JSX is clear
            if (this.state.err)
                comp = <Err />;
            return (
                <div className="App">
                  {comp}
                </div>
            );
        }
    }
    
    export default App;
    
        2
  •  1
  •   Mrchief    7 年前

    两种方法基本上是相同的,但我更喜欢选项1,因为它更容易掌握。你也可以用 babel-plugin-jsx-control-statements#choose 这使得react组件看起来更简单:

    <Choose>
      <When condition={ test1 }>
        <Main />
      </When>
      <When condition={ test2 }>
        <AnotherMain />
      </When>
      <Otherwise>
        <Err />
      </Otherwise>
    </Choose>