在 React JS 中的组件之间切换
Posted
技术标签:
【中文标题】在 React JS 中的组件之间切换【英文标题】:Switching between components in React JS 【发布时间】:2016-03-08 18:39:36 【问题描述】:我想创建一个包含 2 个组件的简单流程。第一个组件被渲染,我点击它上面的一个按钮,这个动作渲染第二个组件。单击第二个组件中的按钮,它应该切换回第一个,但是发生了错误:
警告:React.createElement:类型不应为 null、未定义、 布尔值或数字。它应该是一个字符串(对于 DOM 元素)或 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 />
)
);
索引.js
ReactDOM.render(
<div>
<First />
</div>,
document.getElementById("app-container")
);
【问题讨论】:
无需添加整个错误消息,您也可以将问题清理得更具体,否则没有人可以提供帮助。 【参考方案1】:您只在挂载应用程序时调用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()
。
【讨论】:
【参考方案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>
)
【讨论】:
太棒了:)我从没想过过滤儿童道具【参考方案3】:Hooks 版本(React 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>
);
【讨论】:
【参考方案4】:在渲染函数中,三元运算符将被简单地替换,完整的答案如下:
/** @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'));
其余的都是一样的。
【讨论】:
以上是关于在 React JS 中的组件之间切换的主要内容,如果未能解决你的问题,请参考以下文章
React.js 中的 Function 和 Class 组件之间的确切区别是啥? [复制]
每当我在子组件之间切换时,父组件的 React Router Props 都会刷新