我有一个React组件,render
在组件的方法中我有这样的东西:
render() {
return (
<div>
<div>
// removed for brevity
</div>
{ switch(...) {} }
<div>
// removed for brevity
</div>
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
现在重点是我有两个div
元素,一个在顶部,一个在底部,是固定的.在中间我想要一个switch语句,根据我的状态中的值,我想渲染一个不同的组件.所以基本上,我希望div
始终修复这两个元素,并且只是在中间每次渲染一个不同的组件.我正在使用它来实现多步付款程序).虽然,代码目前它不起作用,因为它给我一个错误说这switch
是意外的.任何想法如何实现我想要的?
Kel*_*oya 87
尝试这个,这也更清晰:在函数中从渲染中取出该开关,然后调用它传递你想要的参数.例如:
renderSwitch(param) {
switch(param) {
case 'foo':
return 'bar';
default:
return 'foo';
}
}
render() {
return (
<div>
<div>
// removed for brevity
</div>
{this.renderSwitch(param)}
<div>
// removed for brevity
</div>
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
1ve*_*ven 34
这是发生的,因为switch
语句是一个statement
,但这里javascript需要一个表达式.
虽然,不建议在render
方法中使用switch语句,但可以使用自调用函数来实现:
render() {
// Don't forget to return a value in a switch statement
return (
<div>
{(() => {
switch(...) {}
})()}
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
Tom*_*cer 34
尽管这是另一种方法,但如果您全力以赴,则可以利用它useCallback
来生成一个仅在必要时重新创建的函数。
假设您有一个应该根据status
prop 进行渲染的组件。使用钩子,您可以按如下方式实现:
const MyComponent = ({ status }) => {
const renderContent = React.useCallback(() => {
switch(status) {
case 'CONNECTING':
return <p className="connecting">Connecting...</p>;
case 'CONNECTED':
return <p className="success">Connected Successfully!</p>
default:
return null;
}
}, [status]);
return (
<div className="container">
{renderContent()}
</div>
);
};
Run Code Online (Sandbox Code Playgroud)
我喜欢这个是因为:
useCallback
钩子确保renderContent
回调在渲染之间重用,除非依赖关系发生status
变化renderContent
函数使用闭包来访问传递给组件的必要属性。一个单独的函数(如接受的答案)需要将 props 传递给它,这可能很麻烦(特别是在使用 TypeScript 时,因为参数也应该正确输入)len*_*kan 27
与其他答案相比,我更倾向于在渲染函数中内联"切换".它使得在该位置可以呈现哪些组件更加清晰.您可以使用普通的旧JavaScript对象实现类似开关的表达式:
render () {
return (
<div>
<div>
{/* removed for brevity */}
</div>
{
{
'foo': <Foo />,
'bar': <Bar />
}[param]
}
<div>
{/* removed for brevity */}
</div>
</div>
)
}
Run Code Online (Sandbox Code Playgroud)
Mat*_*Way 24
我不是任何当前答案的忠实粉丝,因为它们要么太冗长,要么需要您跳过代码以了解发生了什么。
我更喜欢通过创建一个<Switch/>
. 这个组件的工作是获取一个道具,并且只渲染子道具与这个道具匹配的孩子。因此,在下面的示例中,我test
在开关上创建了一个道具,并将其与子项上的value
道具进行了比较,只渲染匹配的道具。
例子:
const Switch = props => {
const { test, children } = props
// filter out only children with a matching prop
return children.find(child => {
return child.props.value === test
})
}
const Sample = props => {
const someTest = true
return (
<Switch test={someTest}>
<div value={false}>Will display if someTest is false</div>
<div value={true}>Will display if someTest is true</div>
</Switch>
)
}
ReactDOM.render(
<Sample/>,
document.getElementById("react")
);
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="react"></div>
Run Code Online (Sandbox Code Playgroud)
您可以根据需要使切换变得简单或复杂。不要忘记对孩子和他们的价值道具进行更健壮的检查。
Luk*_*rns 17
lenkan 的回答是一个很好的解决方案。
<div>
{{ beep: <div>Beep</div>,
boop: <div>Boop</div>
}[greeting]}
</div>
Run Code Online (Sandbox Code Playgroud)
如果你需要一个默认值,那么你甚至可以做
<div>
{{ beep: <div>Beep</div>,
boop: <div>Boop</div>
}[greeting] || <div>Hello world</div>}
</div>
Run Code Online (Sandbox Code Playgroud)
或者,如果这对您来说不太好,那么您可以执行以下操作
<div>
{
rswitch(greeting, {
beep: <div>Beep</div>,
boop: <div>Boop</div>,
default: <div>Hello world</div>
})
}
</div>
Run Code Online (Sandbox Code Playgroud)
和
function rswitch (param, cases) {
if (cases[param]) {
return cases[param]
} else {
return cases.default
}
}
Run Code Online (Sandbox Code Playgroud)
一种使用条件运算符表示渲染块中的一种切换情况的方法:
{this.props.someVar == 1 &&
<SomeContent/>
|| this.props.someVar == 2 &&
<SomeOtherContent />
|| this.props.someOtherVar == 1 &&
<YetSomeOtherContent />
||
<SomeDefaultContent />
}
Run Code Online (Sandbox Code Playgroud)
我建议添加一些括号以确保预期结果,除非掌握运算符优先级...
const [route, setRoute] = useState(INITIAL_ROUTE)
return (
<RouteContext.Provider value={{ route, setRoute }}>
{(() => {
switch (route) {
case Route.Home:
return <PopupHomePage />
case Route.App:
return <PopupAppPage />
default:
return null
}
})()}
</RouteContext.Provider>
Run Code Online (Sandbox Code Playgroud)
function Notification({ text, status }) {
return (
<div>
{(() => {
switch (status) {
case 'info':
return <Info text={text} />;
case 'warning':
return <Warning text={text} />;
case 'error':
return <Error text={text} />;
default:
return null;
}
})()}
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
你可以做这样的事情。
<div>
{ object.map((item, index) => this.getComponent(item, index)) }
</div>
getComponent(item, index) {
switch (item.type) {
case '1':
return <Comp1/>
case '2':
return <Comp2/>
case '3':
return <Comp3 />
}
}
Run Code Online (Sandbox Code Playgroud)
您无法在渲染中进行切换。放置访问一个元素的对象文字的伪切换方法并不理想,因为它会导致所有视图都进行处理,并且可能导致该状态下不存在的 props 的依赖错误。
\n\n这是一种非常干净的方法,不需要提前渲染每个视图:
\n\nrender () {\n const viewState = this.getViewState();\n\n return (\n <div>\n {viewState === ViewState.NO_RESULTS && this.renderNoResults()}\n {viewState === ViewState.LIST_RESULTS && this.renderResults()}\n {viewState === ViewState.SUCCESS_DONE && this.renderCompleted()}\n </div>\n )\n
Run Code Online (Sandbox Code Playgroud)\n\n如果视图状态的条件不仅仅基于简单的属性 \xe2\x80\x93 (例如每行多个条件),那么枚举和getViewState
封装条件的函数是分离此条件逻辑并清理渲染的好方法。
我真的很喜欢/sf/answers/4221949931/中的建议,所以我将其改编为 Typescript,如下所示
import React, { FunctionComponent } from 'react'
import { Optional } from "typescript-optional";
const { ofNullable } = Optional
interface SwitchProps {
test: string
defaultComponent: JSX.Element
}
export const Switch: FunctionComponent<SwitchProps> = (props) => {
return ofNullable(props.children)
.map((children) => {
return ofNullable((children as JSX.Element[]).find((child) => child.props['value'] === props.test))
.orElse(props.defaultComponent)
})
.orElseThrow(() => new Error('Children are required for a switch component'))
}
const Foo = ({ value = "foo" }) => <div>foo</div>;
const Bar = ({ value = "bar" }) => <div>bar</div>;
const value = "foo";
const SwitchExample = <Switch test={value} defaultComponent={<div />}>
<Foo />
<Bar />
</Switch>;
Run Code Online (Sandbox Code Playgroud)
小智 6
import React from 'react';
import ListView from './ListView';
import TableView from './TableView';
function DataView({
currView,
data,
onSelect,
onChangeStatus,
viewTodo,
editTodo,
deleteTodo,
}) {
return (
<div>
{(function () {
switch (currView) {
case 'table':
return (
<TableView
todos={data}
onSelect={onSelect}
onChangeStatus={onChangeStatus}
viewTodo={viewTodo}
editTodo={editTodo}
deleteTodo={deleteTodo}
/>
);
case 'list':
return (
<ListView
todos={data}
onSelect={onSelect}
onChangeStatus={onChangeStatus}
viewTodo={viewTodo}
editTodo={editTodo}
deleteTodo={deleteTodo}
/>
);
default:
break;
}
})()}
</div>
);
}
export default DataView;
Run Code Online (Sandbox Code Playgroud)
比马特·韦的回答有所改进 。
export const Switch = ({ test, children }) => {
const defaultResult = children.find((child) => child.props.default) || null;
const result = children.find((child) => child.props.value === test);
return result || defaultResult;
};
export const Case = ({ children }) => children;
const color = getColorFromTheMostComplexFnEver();
<Switch test={color}>
<Case value="Green">Forest</Case>
<Case value="Red">Blood</Case>
<Case default>Predator</Case>
</Switch>
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Run Code Online (Sandbox Code Playgroud)
我在render()方法中做到了这一点:
render() {
const project = () => {
switch(this.projectName) {
case "one": return <ComponentA />;
case "two": return <ComponentB />;
case "three": return <ComponentC />;
case "four": return <ComponentD />;
default: return <h1>No project match</h1>
}
}
return (
<div>{ project() }</div>
)
}
Run Code Online (Sandbox Code Playgroud)
我试图使render()返回的内容保持整洁,因此我将逻辑放在上面的'const'函数中。这样,我也可以整齐地缩进开关盒。
归档时间: |
|
查看次数: |
87739 次 |
最近记录: |