【发布时间】:2020-10-22 20:16:23
【问题描述】:
我希望我的组件的用户能够传入一个组件对象,并且我希望允许他们使用基于函数或类的组件。
type InputComponents = Record<string, React.ComponentType>
这允许 FC 或类组件,但我没有找到关于如何呈现它们的明确指南。
const inputComponents = {
a: ({ placeholder }) => ( // Functional component
<input
type="text"
value={state.a}
placeholder={placeholder}
onChange={(e) => {
const value = e.currentTarget.value;
setState((s) => ({ ...s, a: value }));
}}
/>
),
b: InputClass // Class component
};
两个组件都可以很好地渲染,没有 Typescript 像这样抱怨:
const A = inputComponents.a;
const B = inputComponents.b;
<A placeholder="Type something" />
<B placeholder="Type something" />
但这实际上具有误导性 - 功能性 (a) 每次按键都会失去焦点。
使功能组件每次按键都不会失去焦点的唯一方法是这样的:
inputComponents.a({ placeholder: 'Type something' })
Typescript 甚至不认为这是渲染组件的有效方法,但它是唯一完全有效的方法......它会出现“此表达式不可调用”的错误。并且 Class 组件也失败了,所以我必须这样做:
// Render as JSX for class components and call as a function for FC ones...
Component.prototype.isReactComponent ? <Component placeholder={x} /> : Component({ placeholder: x })
您可以在此处查看实际问题:
function SomeComponent({ inputComponents }) {
const B = inputComponents.b;
const C = inputComponents.c;
return (
<div className="SomeComponent">
<p>This FC component doesn't loose focus:</p>
{inputComponents.a({ placeholder: 'Type something' })}
<p>This one does:</p>
<B placeholder="Type something" />
<p>Rendering a class component as JSX works though:</p>
<C placeholder="Type something" />
</div>
);
}
class InputClass extends React.Component {
state = {
value: ''
};
render() {
return (
<input
type="text"
value={this.state.value}
placeholder={this.props.placeholder}
onChange={(e) => {
this.setState({ value: e.currentTarget.value });
}}
/>
);
}
}
function App() {
const [state, setState] = React.useState({
a: '',
b: ''
});
const inputComponents = {
a: ({ placeholder }) => (
<input
type="text"
value={state.a}
placeholder={placeholder}
onChange={(e) => {
const value = e.currentTarget.value;
setState((s) => ({ ...s, a: value }));
}}
/>
),
b: ({ placeholder }) => (
<input
type="text"
value={state.b}
placeholder={placeholder}
onChange={(e) => {
const value = e.currentTarget.value;
setState((s) => ({ ...s, b: value }));
}}
/>
),
c: InputClass
};
return (
<div className="App">
<SomeComponent inputComponents={inputComponents} />
</div>
);
}
ReactDOM.render(<App />, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script>
<div id="app"></div>
React 坏了吗?或者,在不依赖黑客 TS 错误和使用isReactComponent 之类的内部内容的情况下,处理此问题的正确方法是什么?谢谢
【问题讨论】:
-
在这里更新了演示
标签: javascript reactjs