blog icon indicating copy to clipboard operation
blog copied to clipboard

使用React在不同的DOM元素中渲染组件

Open Hancoson opened this issue 7 years ago • 0 comments

我刚刚开始使用React。在我的项目中,我创建了一个button。当用户点击这个创建的button时候,有些复杂的字母“a”出现在页面上。

然而,在我的html中,这个字母在按钮的兄弟元素当中,下面代码是我如何解决这个渲染元素的问题。

Attempt #1:

import React from 'react';
import ReactDOM from 'react-dom';

const Letter = React.createClass({
    render() {
        return (
            // lots of HTML stuff here...
        )
    }
});

var CapitalAButton = React.createClass({
    getInitialState: function(){
        return { showCapitalA: false  };
    },

    showCapitalA: function(){
        this.setState({
            showCapitalA: true
        });
    },
    
    render: function() {
	return (
	    <div id="capital-button" onClick={this.showCapitalA}>
	        A
	        { this.state.showCapitalA? ReactDOM.render(<Letter />, document.querySelector('#letter')) : null }	    
	    </div>
	)
    }
});

var ButtonChoices = React.createClass({
    render: function() {
	return (
	    <CapitalAButton />
	)
    }
});

ReactDOM.render(
    <div id="a">
        <ButtonChoices />
    </div>,
    document.querySelector('#button-group')
);

这个问题被我在45行创建。我试图创建的按钮放在了id为button-group元素当中,而不是 container 或其他,包括任何元素本身。

结果是,在27行代码,当我最后得到渲染 <Letter /> 元素的后,我告诉React找到一个不同的Dom元素并把组件写入到里面,这个Dom 为 #letter

运行后,会得到这样的结果:

"Warning: _renderNewRootComponent(): Render methods should be a pure function of props and state; triggering nested component updates from render is not allowed. If necessary, trigger nested updates in componentDidUpdate. Check the render method of CapitalAButton."

如果一个框架运行时给出这样的错误提示,我就要注意了,所以看下面……

Attempt #2

此时,最好的方法可能是设置原始组件在 container,这个组件包含这样一个事实,就是他有一个加 button-group 的id。但是我任就是在瞎搞。

我查看了一些资料关于如何实现 componentDidUpdate,如下:

  • http://stackoverflow.com/questions/24502898/show-or-hide-element-in-react-js
  • https://facebook.github.io/react/docs/component-specs.html#updating-componentdidupdate
  • http://busypeoples.github.io/post/react-component-lifecycle/
  • https://facebook.github.io/react/docs/top-level-api.html#reactdom.unmountcomponentatnode

生成的代码:

import React from 'react';
import ReactDOM from 'react-dom';

const Letter = React.createClass({
  render() {
	  return (
      // same html stuff ...
	  )
  } 
});

var CapitalAButton = React.createClass({
  getInitialState: function(){
	  return { showCapitalA: false  };
  },

  componentDidUpdate: function(prevProps, prevState){
	  prevState.showCapitalA? ReactDOM.unmountComponentAtNode(document.querySelector("#letter")) : ReactDOM.render(<Letter />, document.querySelector('#letter'));
  },

  toggleCapitalA: function(){
	  this.state.showCapitalA? this.setState({showCapitalA: false}) : this.setState({showCapitalA: true})
  },
  
  render: function() {
	    return (
	      <div id="capital-button" onClick={this.toggleCapitalA}>
	      A
	      </div>
	    )
    }
});

var ButtonChoices = React.createClass({
  render: function() {
	  return (
	    <CapitalAButton />
	  )
  }
});

ReactDOM.render(
    <div id="a">
        <ButtonChoices />
    </div>,
    document.querySelector('#button-group')
);

这里有许多重大的变化。首先,这个按钮有状态,用来表示字母是否可见,当用户点击这个按钮时,状态改变。

随着状态的改变触发 componentDidUpdate 监听器,切换字母的显示与否。

结论

通过这个有趣的例子学习了React中“状态”的工作,以及一些他提供的有趣的函数。我也期待着学习如何做正确的。


有很多地方可能翻译的不准确,感兴趣的同学可以查看原文>>

查看原文:地址


我的博客

Hancoson avatar Feb 13 '17 03:02 Hancoson