在React JS

时间:2015-12-03 23:11:50

标签: javascript node.js reactjs components browserify

我想用2个组件创建一个简单的流程。第一个组件被渲染,我单击它上面的一个按钮,这个动作渲染第二个组件。单击第二个组件中的按钮,它应该切换回第一个组件,但是发生错误:

  

警告:React.createElement:type不应为null,未定义,   布尔值或数字。它应该是一个字符串(对于DOM元素)或a   ReactClass(用于复合组件)。检查渲染方法   exports。warning @ react.js:20728ReactElementValidator.createElement   @ react.js:9853t.exports.React.createClass.render @   bundle.js:1ReactCompositeComponentMixin._renderValidatedComponentWithoutOwnerOrContext   @ react.js:6330ReactCompositeComponentMixin._renderValidatedComponent   @ react.js:6350wrapper @   react.js:12868ReactCompositeComponentMixin._updateRenderedComponent @   react.js:6303ReactCompositeComponentMixin._performComponentUpdate @   react.js:6287ReactCompositeComponentMixin.updateComponent @   react.js:6216wrapper @   react.js:12868ReactCompositeComponentMixin.performUpdateIfNecessary @   react.js:6164ReactReconciler.performUpdateIfNecessary @   react.js:13667runBatchedUpdates @ react.js:15356Mixin.perform @   react.js:17245Mixin.perform @ react.js:17245assign.perform @   react.js:15313flushBatchedUpdates @ react.js:15374wrapper @   react.js:12868Mixin.closeAll @ react.js:17311Mixin.perform @   react.js:17258ReactDefaultBatchingStrategy.batchedUpdates @   react.js:8842batchedUpdates @   react.js:15321ReactEventListener.dispatchEvent @ react.js:10336   react.js:20250

     

未捕获错误:不变违规:元素类型无效:预期   字符串(用于内置组件)或类/函数(用于复合   组件)但得到:对象。检查渲染方法   exports。invariant @ react.js:20250instantiateReactComponent @   react.js:18268ReactCompositeComponentMixin._updateRenderedComponent @   react.js:6312ReactCompositeComponentMixin._performComponentUpdate @   react.js:6287ReactCompositeComponentMixin.updateComponent @   react.js:6216wrapper @   react.js:12868ReactCompositeComponentMixin.performUpdateIfNecessary @   react.js:6164ReactReconciler.performUpdateIfNecessary @   react.js:13667runBatchedUpdates @ react.js:15356Mixin.perform @   react.js:17245Mixin.perform @ react.js:17245assign.perform @   react.js:15313flushBatchedUpdates @ react.js:15374wrapper @   react.js:12868Mixin.closeAll @ react.js:17311Mixin.perform @   react.js:17258ReactDefaultBatchingStrategy.batchedUpdates @   react.js:8842batchedUpdates @   react.js:15321ReactEventListener.dispatchEvent @ react.js:10336

第一部分:

/** @jsx React.DOM */

var Second = require('components/second/view.jsx');

module.exports = React.createClass({

handlerClick: function () {
    ReactDOM.render(
        <Second />,
        document.getElementById("app-container")
    )
},

render: function() {
  return (
    <input type="button" value="COMPONENT 1" onClick={this.handlerClick} />
  )
}
});

第二部分:

/** @jsx React.DOM */

var First = require('components/first/view.jsx');

module.exports = React.createClass({

handlerClick: function () {
    ReactDOM.render(
        <First />,
        document.getElementById("app-container")
    )
},

render: function() {
  return (
    <input type="button" value="COMPONENT 2" onClick={this.handlerClick} />
  )
}
});

Index.js

ReactDOM.render(
    <div>
        <First />
    </div>,
    document.getElementById("app-container")
);

4 个答案:

答案 0 :(得分:6)

您只能在挂载应用程序时调用ReactDOM.render()。安装后,您再也不会在同一个挂载点上再次调用ReactDOM.render()。 [*见下面的更新。]

请记住,您的视图是道具和州的功能。要更改视图,请触发状态更改。

我建议这样的事情:

var Parent = React.createClass({

    getInitialState: function () {
        return {
            active: 'FIRST'
        };
    },

    handleClick: function () {
        var active = this.state.active;
        var newActive = active === 'FIRST' ? 'SECOND' : 'FIRST';
        this.setState({
            active: newActive
        });
    },

    render: function () {

        var active = this.state.active;

        return (
            <div>
                {active === 'FIRST' ? (
                    <First />
                ) : active === 'SECOND' ? (
                    <Second />
                ) : null}
                <button type="button" onClick={this.handleClick}>
                    Toggle
                </button>
            </div>
        );

     }

});

并将Parent设为根节点。即。

ReactDOM.render(<Parent />, document.getElementById('app-container'));

更新:我知道您可以致电ReactDOM.render() multiple times on the same mount point。这通常与您初始化应用程序的位置相同。不过,你肯定不会从React组件中调用ReactDOM.render()

答案 1 :(得分:2)

这是创建SwitchComponents组件的非常简单的解决方案:

// SwitchComponents.js:

import React from 'react';

export default function SwitchComponents({ active, children }) {
  // Switch all children and return the "active" one
  return children.filter(child => child.props.name == active)
}

并将其导入您的应用程序:

// App.js
import SwitchComponents from './components/SwitchComponents';

export default function App() {

const [activeComponent, setActiveComponent] = useState("questions")

return (
    <SwitchComponents active={activeComponent}>
      <Home name="home" />
      <Instructions name="instructions" />
      <FileboxContainer name="filebox" />
      <Questions name="questions" />
    </SwitchComponents>
  )
}

答案 2 :(得分:1)

渲染函数中的

三元运算符将被简单替换,完整答案将如下:

    /** @jsx React.DOM */

    var Parent = React.createClass({
    getInitialState: function () {
        return {
            active: 'FIRST'
        };
    },

        handleClick: function () {
            var active = this.state.active;
            var newActive = active === 'FIRST' ? 'SECOND' : 'FIRST';
            this.setState({
                active: newActive
            });
        },

        render: function () {

            var active = this.state.active;

            return (
                <div>
                    {(active === 'FIRST') && <First /> }
                    {(active === 'SECOND') && <Second /> }
                    <button type="button" onClick={this.handleClick}>
                        Toggle
                    </button>
                </div>
            );

         }
    });


  ReactDOM.render(<Parent />, document.getElementById('app-container'));

休息将是一样的。

答案 3 :(得分:0)

挂钩版本(反应16.8 +):

最低版本。

import React, { useState } from 'react';

export default function App() {
  const [toggle, setToggle] = useState(true);
  const toggleChecked = () => setToggle(toggle => !toggle);
  return (
     <div>
        {toggle && <First /> }
        {!toggle && <Second /> }
        <button type="button" onClick={this.toggleChecked}>
           Toggle
        </button>
     </div>
  );
}