javascript - การละเมิดเงื่อนไขคงที่เมื่อใช้ห้องสมุดคอมโพเนนต์ภายนอก
ฉันกำลังทำงานเพื่อปรับเปลี่ยนคอมโพเนนต์ React ที่เขียนด้วย TypeScript การเปลี่ยนแปลงที่ฉันกำลังทำในฐานโค้ดเกี่ยวข้องกับการลบคอมโพเนนต์ที่เราเป็นเจ้าของออกเพื่อใช้ไลบรารีภายนอก react-dual-listbox แทน
ทันทีที่ฉันนำเข้าการพึ่งพา การทดสอบทั้งหมดที่มีอยู่ของฉันเริ่มล้มเหลว และฉันไม่แน่ใจว่าทำไม ข้อผิดพลาดที่ฉันได้รับคือ
Error: Uncaught [Invariant Violation: Element type is invalid: expected a string
(for built-in components) or a class/function (for composite components) but got:
undefined. You likely forgot to export your component from the file it's defined in,
or you might have mixed up default and named imports.
Check the render method of `default_1`.
นี่คือไฟล์ทดสอบของฉัน:
import { shallow, configure, mount } from 'enzyme';
import * as React from 'react';
import PolicyEditor, { PolicyEditorProps } from '../PolicyEditor';
import * as Adapter from 'enzyme-adapter-react-16';
configure({ adapter: new Adapter() });
const defaultProps: PolicyEditorProps = {
id: 'id',
serviceId: 'service id',
data: { data: { policy: { id: '1', name: 'policy', permissions: [] } } },
permissionsData: { data: { service: { id: '1', permissions: [] } } },
create: jest.fn(),
update: jest.fn(),
updatePermissions: jest.fn(),
delete: jest.fn(),
back: jest.fn(),
};
describe('PolicyEditor.tsx', () => {
it('sets the state when the name is changed', done => {
const wrapper = mount(<PolicyEditor {...defaultProps} />);
const input = wrapper.find('input[id="policyName"]').first();
const event = { target: { value: 'new policy name' } };
input.simulate('change', event);
process.nextTick(() => {
expect(wrapper.state().name).toEqual('new policy name');
done();
});
});
});
ส่วนประกอบ :
import 'react-dual-listbox/lib/react-dual-listbox.css';
import * as React from 'react';
import { MutationFn } from 'react-apollo';
import { isQueryReady, isQueryLoading } from '../util/actionHelpers';
import {
Permission,
PolicyWithPermissions,
ServicePermissionsQueryResult,
PolicyQueryResult,
} from './types';
import AuthModal from '../shared/AuthModal';
import { Container, Row, Col, Label, Button, Form, FormGroup, Input } from 'reactstrap';
import DualListBox from 'react-dual-listbox';
export interface PolicyEditorProps {
id?: string;
serviceId: string;
data: PolicyQueryResult;
permissionsData: ServicePermissionsQueryResult;
create: MutationFn;
update: MutationFn;
updatePermissions: MutationFn;
delete: MutationFn;
back(): void;
}
interface PolicyEditorState {
name: string;
selectedPermissions: Permission[];
}
export default class extends React.Component<PolicyEditorProps, PolicyEditorState> {
static getDerivedStateFromProps(
nextProps: PolicyEditorProps,
prevState: PolicyEditorState
): Partial<PolicyEditorState> | null {
if (nextProps.id && isQueryReady(nextProps.data)) {
const policy: PolicyWithPermissions = nextProps.data.data!.policy;
return {
name: policy.name,
selectedPermissions: policy.permissions,
};
}
if (!nextProps.id) {
return {
name: '',
};
}
return null;
}
constructor(props: PolicyEditorProps) {
super(props);
this.state = {
name: '',
selectedPermissions: [],
};
}
render() {
const isEdit: boolean = !!this.props.id;
if (isEdit) {
if (isQueryLoading(this.props.data)) {
return <div>Loading...</div>;
}
if (this.props.data.error !== undefined) {
return <div>Something went wrong!</div>;
}
}
const { loading, error } = this.props.permissionsData;
return (
<AuthModal title="Policy Editor" isOpen={true} toggle={this.props.back}>
<Form>
<FormGroup>
<Label for="policyName">Name</Label>
<Input
id="policyName"
onChange={e => this.setState({ name: e.target.value })}
value={this.state.name}
/>
</FormGroup>
{isEdit ? (
<div>
<hr />
{loading ? (
<div>Loading...</div>
) : error ? (
<div>Error</div>
) : (
<Container className="m-2">
<Row>
<Col className="text-center" xs="6">
Available Permissions
</Col>
<Col className="text-center" xs="6">
Current Permissions
</Col>
</Row>
<DualListBox
canFilter={true}
options={this.props.permissionsData.data!.service.permissions.map(p => ({
value: p.id,
label: p.name,
}))}
selected={this.state.selectedPermissions.map(p => p.id)}
onChange={this.updateSelectedPermissions}
/>
</Container>
)}
<FormGroup>
<Row>
<Col xs={{ size: 1 }}>
<Button onClick={this.onUpdate} color="success">
Update
</Button>
</Col>
<Col xs={{ size: 1, offset: 1 }}>
<Button onClick={this.onDelete} color="danger">
Delete
</Button>
</Col>
</Row>
</FormGroup>
</div>
) : (
<FormGroup>
<Button color="success" onClick={this.onCreate}>
Create
</Button>
</FormGroup>
)}
</Form>
</AuthModal>
);
}
}
ข้อความแสดงข้อผิดพลาดดูเหมือนจะลึกลับ มันดูเหมือนจะบอกฉันว่ามันคาดหวังว่า บางสิ่ง จะเป็นสตริง แต่กลับเป็น undefined ฉันไม่แน่ใจว่ามันคืออะไรที่เป็น undefined อย่างชัดเจน อย่างไรก็ตาม ฉันสามารถทำให้การทดสอบผ่านได้ถ้าฉันไม่เรนเดอร์ DualListBox แต่สิ่งนั้นก็ไม่ช่วยแก้ปัญหาของฉัน
สิ่งที่แปลกก็คือมันทำงานได้ตามที่คาดไว้ในเบราว์เซอร์โดยไม่มีข้อผิดพลาด และปัญหามีเฉพาะในการทดสอบของฉันเท่านั้น ดูเหมือนว่าคนที่มีข้อความแสดงข้อผิดพลาดเหมือนกันจะพบว่ามันเป็นปัญหาการนำเข้า แต่ถ้ามันทำงานในเบราว์เซอร์ แปลว่าการน่ำเข้านั้นถูกต้องใช่ไหม?
มีอะไรบางอย่างที่ฉันพลาดหรือไม่เข้าใจตรงนี้หรือเปล่า?