【问题标题】:How do you change what jsx blocks are being rendered from inside a same class?你如何改变从同一个类中渲染的 jsx 块?
【发布时间】:2019-03-21 06:21:30
【问题描述】:

我仍在学习 React 的基础知识,我想做一些引起我注意的事情。这是关于渲染两件事。是否有可能或什至可能只是更改使用函数呈现的内容,然后使用按钮或计时器分别调用这些函数?

这是一个示例代码,展示了它如何渲染两个完全不同的东西。它应该呈现一个显示“状态:开启”或“状态:关闭”的按钮。当您单击按钮时,状态会发生变化。而且,整个渲染方法都被切换了......或者至少这是应该发生的事情。

class Flicker{
    constructor(props){
        super(props);
        this.state = {mode: "on"};
    }
    flipOn(){
        this.setState({mode: "on"})
    }
    flipOff(){
        this.setState({mode: "off"})
    }
    if (this.state.mode == "on"){
        render() {
            return(
                <button onClick={this.flipOn}>State: On</button>
            );
        }
    } else if (this.state.mode == "off"){
        render() {
            return(
                <button onClick={this.flipOff}>State: Off</button>
            );
        }
    }
}
export default Flicker;

如果这不是对 jsx 在应用程序上呈现的内容进行此类更改的正确方法,应该如何进行?

【问题讨论】:

    标签: javascript reactjs ecmascript-6 jsx


    【解决方案1】:

    你的组件改变了状态。状态是布尔值——开(真)或不开(假)。由于您的状态在两个值之间切换,因此您可以使用单一方法 (toggle)。既然我们检查之前的状态,最好setState via updater

    您需要绑定method to this,通过在构造函数中使用bind(方法4)或通过实例方法(方法5)使用箭头函数。

    现在在(单)渲染中,只需要根据on的状态改变text即可:

    class Flicker extends React.Component{
      state = { on: true };
    
      toggle = () =>
        this.setState(({ on }) => ({ on: !on }));
    
      render() {
        const text = this.state.on ? 'On' : 'Off';
    
        return (
          <button onClick={this.toggle}>State: {text}</button>
        );
      }
    }
    
    ReactDOM.render(
      <Flicker />,
      demo
    );
    <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    
    <div id="demo"></div>

    现实世界的例子

    按钮可能应该通过道具获得ontoggle。现在它们都可以在外面使用了,Flicker 唯一关心的就是点击时调用toggle,并根据on 更改文本:

    const Toggler = ({ on, toggle }) => (
      <button onClick={toggle}>
        State: {on ? 'On' : 'Off'}
      </button>
    );
    
    class Flicker extends React.Component {
      state = { on: true };
    
      toggle = () =>
        this.setState(({ on }) => ({ on: !on }));
      
      render() {
        const { on } = this.state;
      
        return (
          <div>
            <Toggler toggle={this.toggle} on={on} />
            {on &&
              'I\'m displayed only when I\'m On'
            }
          </div>
        );
      }
    }
    
    ReactDOM.render(
      <Flicker />,
      demo
    );
    <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    
    <div id="demo"></div>

    【讨论】:

    • 如果呈现的状态还呈现文本或表单或其他内容,以及状态更改按钮怎么办?这也适用于诸如此类的事情吗?
    • 这是一个按钮,一个按钮应该很简单。如果您想要更复杂的东西,请创建其他简单的组件并将它们组合在一起。在这种情况下,按钮不应该有它自己的状态。 In 应该通过 prop 获取 on 状态,并通过回调来更改父级中 on 的状态。现在您可以使用外部的 on 值做任何您想做的事情。
    • 我添加了一个实际使用中的 Flicker 示例。
    • 我最初提出的示例代码并不是关于按钮有自己的状态。名为 mode 的变量具有字符串“On”或字符串“Off”的值,通过按下按钮会改变。因此,它的目的是尽可能简单。该按钮的唯一功能,而不是打开或关闭状态,是关于渲染打开或关闭整个 div 元素,其中包含更多 jsx 元素。
    • 这是 Flicker 类的基本意图。这只是为了解决一个疑问,这就是为什么这个想法的样本是一个简单的开关。不过不要误会我的意思,您的建议同样有效,尽管不是针对我指定的问题。
    【解决方案2】:

    将条件逻辑放在 render() 方法中。

    这样的……

    class Example extends React.Component {
      // the rest of your code
    
      render() {
         const { mode } = this.state;
              return(
                  <div>
                     {mode ==="on" && <button onClick={this.flipOn}>State: On</button> }
                     {mode === "off" && <button onClick={this.flipOff}>State: Off</button>}
                   </div>
              )
        }
    }

    【讨论】:

    • 所以它会是:渲染>逻辑>返回?
    • 谢谢 Filip,这正是我需要知道的!
    • @Flip 我编辑了你的答案。在渲染中使用 if else 是不好的。查看编辑后的答案,如果您有任何疑问,请告诉我
    【解决方案3】:

    你的想法是对的——但是在一个类中只有一个渲染方法。您的逻辑确实属于渲染内部。这应该可以满足您的需求:

    class Flicker extends React.Component {
        constructor(props){
            super(props);
            this.state = {mode: "On"};
        }
    
        flipOn(){
            this.setState({mode: "On"})
        }
    
        flipOff(){
            this.setState({mode: "Off"})
        }
    
        render () {
            return (
                <button onClick={(this.state.mode === 'Off') ? this.flipOn : this.flipOff}>State: {this.state.mode}</button>
            )
        }
    }
    
    export default Flicker;

    【讨论】:

    • flipOff 从来没有在你的代码中调用过,也没有扩展 React 组件这个类是如何工作的
    • 谢谢 - 进行了相应的编辑。 @Dan,它非常灵活 - 基本上你的逻辑确实属于渲染,但你如何选择这样做取决于你。我相信根据状态返回一个不同的按钮有点矫枉过正。您可以使用具有不同属性的相同按钮,但这取决于您。
    猜你喜欢
    • 2018-01-25
    • 2017-11-30
    • 2022-12-14
    • 2018-07-19
    • 2020-05-27
    • 1970-01-01
    • 1970-01-01
    • 2020-06-28
    • 2020-12-16
    相关资源
    最近更新 更多