我有一个React组件,在组件的渲染方法中,我有这样的东西:
render() {
return (
<div>
<div>
// removed for brevity
</div>
{ switch(...) {} }
<div>
// removed for brevity
</div>
</div>
);
}
Now the point is that I have two div elements, one at the top and one at the bottom, that are fixed. In the middle I want to have a switch statement, and according to a value in my state I want to render a different component. So basically, I want the two div elements to be fixed always, and just in the middle to render a different component each time. I'm using this to implement a multi-step payment procedure). Though, as is the code currently it doesn't work, as it gives me an error saying that switch is unexpected. Any ideas how to achieve what I want?
我不太喜欢当前的任何答案,因为它们要么太啰嗦,要么需要您在代码中跳跃才能理解发生了什么。
我更喜欢用一个更以react组件为中心的方式来做这件事,通过创建一个<Switch/>。这个组件的任务是获取一个道具,并且只呈现子道具与该道具匹配的子元素。所以在下面的例子中,我在开关上创建了一个测试道具,并将其与子节点上的值道具进行比较,只渲染匹配的值道具。
例子:
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")
);
<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>
您可以根据自己的需要进行简单或复杂的切换。不要忘记对子节点及其值道具执行更健壮的检查。
这个助手应该可以做到这一点。
使用示例:
{componentSwitch(3, (switcher => switcher
.case(1, () =>
<p>It is one</p>
)
.case(2, () =>
<p>It is two</p>
)
.default(() =>
<p>It is something different</p>
)
))}
助手:
interface SwitchCases<T> {
case: (value: T, result: () => React.ReactNode) => SwitchCases<T>;
default: (result: () => React.ReactNode) => SwitchCases<T>;
}
export function componentSwitch<T>(value: T, cases: (cases: SwitchCases<T>) => void) {
var possibleCases: { value: T, result: () => React.ReactNode }[] = [];
var defaultResult: (() => React.ReactNode) | null = null;
var getSwitchCases: () => SwitchCases<T> = () => ({
case: (value: T, result: () => React.ReactNode) => {
possibleCases.push({ value: value, result });
return getSwitchCases();
},
default: (result: () => React.ReactNode) => {
defaultResult = result;
return getSwitchCases();
},
})
// getSwitchCases is recursive and will add all possible cases to the possibleCases array and sets defaultResult.
cases(getSwitchCases());
// Check if one of the cases is met
for(const possibleCase of possibleCases) {
if (possibleCase.value === value) {
return possibleCase.result();
}
}
// Check if the default case is defined
if (defaultResult) {
// Typescript wrongly assumes that defaultResult is always null.
var fixedDefaultResult = defaultResult as (() => React.ReactNode);
return fixedDefaultResult();
}
// None of the cases were met and default was not defined.
return undefined;
}
Lenkan的回答是一个很好的解决方案。
<div>
{{ beep: <div>Beep</div>,
boop: <div>Boop</div>
}[greeting]}
</div>
如果需要一个默认值,那么您甚至可以这样做
<div>
{{ beep: <div>Beep</div>,
boop: <div>Boop</div>
}[greeting] || <div>Hello world</div>}
</div>
或者,如果这对你来说不太好,那么你可以做一些
<div>
{
rswitch(greeting, {
beep: <div>Beep</div>,
boop: <div>Boop</div>,
default: <div>Hello world</div>
})
}
</div>
with
function rswitch (param, cases) {
if (cases[param]) {
return cases[param]
} else {
return cases.default
}
}