javascript 在 React JS 中的组件之间切换
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34078033/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Switching between components in React JS
提问by user5512965
I want to create a simple flow, with 2 components. The first component is rendered, I click a button on it and this action render the second component. Clicking on the button from the second component, it should switch back to the first one, but instead, an error occurred:
我想创建一个简单的流程,包含 2 个组件。第一个组件被渲染,我点击它上面的一个按钮,这个动作渲染第二个组件。单击第二个组件中的按钮,它应该切换回第一个组件,但发生了错误:
Warning: React.createElement: type should not be null, undefined, boolean, or number. It should be a string (for DOM elements) or a ReactClass (for composite components). Check the render method of
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:20250Uncaught Error: Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object. Check the render method of
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
警告:React.createElement:类型不应为空、未定义、布尔值或数字。它应该是一个字符串(对于 DOM 元素)或一个 ReactClass(对于复合组件)。检查渲染方法
exports
[email protected]:[email protected]:[email protected]:1ReactCompositeComponentMixin._renderValidatedComponentWithoutOwnerOrContext@react.js:6330ReactCompositeComponentMixin._react.js50react.createClass.render@react. :12868ReactCompositeComponentMixin._updateRenderedComponent@react.js:6303ReactCompositeComponentMixin._performComponentUpdate@react.js:[email protected]:[email protected]:12868ReactCompositeComponentMixin.js:12868ReactCompositeComponentMixin.React.js:12868ReactCompositeComponentMixin.React.6303ReactCompositeComponentMixin._performComponentUpdate@react.js:6287ReactCompositeComponentMixin.updates:12868ReactCompositeComponentMixin. .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:15321ReactEventListener.dispatchEvent @ react.js0未捕获的错误:不变违规:元素类型无效:预期为字符串(对于内置组件)或类/函数(对于复合组件)但得到:对象。检查渲染方法
exports
.invariant @react.js:20250instantiateReactComponent @react.js:18268ReactCompositeComponentMixin._updateRenderedComponent @react.js:6312ReactCompositeComponentMixin._performComponentUpdate @react.js:6287ReactCompositeComponentMixin.updateComponent @react.js:6268ReactCompositeComponentMixin._updateRenderedComponent @react.js:6312ReactCompositeComponentMixin._performComponentUpdate @react.js:[email protected]:6268ReactReactCompositeComponentMixin._updateRenderedComponent @react.js:626216. :6164ReactReconciler.performUpdateIfNecessary @react.js:13667runBatchedUpdates @react.js:15356Mixin.perform @react.js:17245Mixin.perform @react.js:17245assign.perform @react.js:15313 @react.js:15356Mixin.perform @react.js:15313 @react.js:react.js4perform :12868Mixin.closeAll @ react.js:17311Mixin.perform @ react.js:17258ReactDefaultBatchingStrategy.batchedUpdates @ react.js:8842batchedUpdates @ react.js:15321ReactEventListener.dispatchEvent @ react.js:10336
First component:
第一个组件:
/** @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} />
)
}
});
Second Component:
第二部分:
/** @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
索引.js
ReactDOM.render(
<div>
<First />
</div>,
document.getElementById("app-container")
);
回答by David L. Walsh
You only ever call ReactDOM.render()
when you mount the application. Once mounted, you never call ReactDOM.render()
again on the same mount point. [*see update below.]
您只有ReactDOM.render()
在安装应用程序时才会调用。挂载后,您再也不会ReactDOM.render()
在同一个挂载点上调用。[*见下面的更新。]
Remember that your view is a function of your props and state. To change your view, trigger a change in state.
请记住,您的视图是您的道具和状态的函数。要更改您的视图,请触发状态更改。
I suggest something like this:
我建议是这样的:
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>
);
}
});
And make the Parent the root node. i.e.
并使父节点成为根节点。IE
ReactDOM.render(<Parent />, document.getElementById('app-container'));
UPDATE:I've since learned you cancall ReactDOM.render()
multiple times on the same mount point. This would typically be in the same place you initialise the application. Nevertheless, you certainly don't call ReactDOM.render()
from inside a React component.
更新:从那以后,我了解到您可以ReactDOM.render()
在同一个挂载点上多次调用。这通常与您初始化应用程序的位置相同。尽管如此,您肯定不会ReactDOM.render()
从 React 组件内部调用。
回答by DilipCoder
in the render function ternary operator will be replaced simply and the full answer will be like:
在渲染函数中,三元运算符将被简单地替换,完整的答案将如下所示:
/** @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'));
Rest will be same.
休息会一样。
回答by Hunter
Hooks version (React 16.8+):
钩子版本(React 16.8+):
Minimal version.
最小版本。
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>
);
}
回答by Maycow Moura
Here's a very simple solution creating a SwitchComponents
component:
这是创建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)
}
And import it in your app:
并将其导入您的应用程序:
// 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>
)
}
If you don't wanna pass the "name" property, you can you the solution below:
如果您不想传递“name”属性,您可以使用以下解决方案:
return children.filter(child => child.type.name == active)
But that's the name you give to your functionwhen you define you component, like this:
但这是您在定义组件时为函数取的名称,如下所示:
export default function MyFunctionName() { ... } // this is the name
Even if you import it with another name, that's still gonna be the name you must use.
即使您使用其他名称导入它,这仍然是您必须使用的名称。