1

我正在尝试使用打字稿制作简单的 CRUD 示例并做出反应。我是打字稿的新手,所以我不完全理解这个错误应该是什么意思。

我已经在组件中完成了添加/编辑功能,但我想在单击时动态调用该组件,并将其显示为页面上的弹出窗口或模式窗口,该窗口显示网格而不重定向到另一条路线。

当我尝试调用我的其他组件AddNaselje时,出现以下 typescript 编译器错误:

Type '{}' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<AddNaselje> & Readonly<{ children?: ReactNode; }> ...'.
  Type '{}' is not assignable to type 'Readonly<RouteComponentProps<{}>>'.
    Property 'match' is missing in type '{}'.

这是我的父组件代码,其中显示了显示城市的项目网格:

import * as React from 'react';
import { RouteComponentProps } from 'react-router';
import { Link, NavLink } from 'react-router-dom';
import { AddNaselje } from './AddNaselje';

interface FetchNaseljeDataState {
    nasList: NaseljeData[];
    loading: boolean;
    showModal: boolean
}

export class FetchNaselje extends React.Component<RouteComponentProps<{}>, FetchNaseljeDataState> {
    constructor() {
        super();
        this.state = { nasList: [], loading: true, showModal: false };
        fetch('api/Naselje/Index')
            .then(response => response.json() as Promise<NaseljeData[]>)
            .then(data => {
                this.setState({ nasList: data, loading: false });
            });
        // This binding is necessary to make "this" work in the callback  
        this.handleDelete = this.handleDelete.bind(this);
        this.handleEdit = this.handleEdit.bind(this);
    }

    public render() {
        let contents = this.state.loading
            ? <p><em>Loading...</em></p>
            : this.renderNaseljeTable(this.state.nasList);
        return <div>
            <h1>Naselje Data</h1>
            <p>This component demonstrates fetching Naselje data from the server.</p>
            <p>
                <Link to="/addnaselje">Create New</Link>
                <AddNaselje></AddNaselje> /*this is where I get compiler error*/
            </p>
            {contents}
        </div>;
    }

    showModal = () => {
        this.setState({
            ...this.state,
            showModal: this.state.showModal
        });
    }

    // Handle Delete request for an naselje  
    private handleDelete(id: number) {
        if (!confirm("Do you want to delete naselje with Id: " + id))
            return;
        else {
            fetch('api/Naselje/Delete/' + id, {
                method: 'delete'
            }).then(data => {
                this.setState(
                    {
                        nasList: this.state.nasList.filter((rec) => {
                            return (rec.idnaselje != id);
                        })
                    });
            });
        }
    }
    private handleEdit(id: number) {
        this.props.history.push("/naselje/edit/" + id);
    }

    // Returns the HTML table to the render() method.  
    private renderNaseljeTable(naseljeList: NaseljeData[]) {
        return <table className='table'>
            <thead>
                <tr>
                    <th></th>
                    <th>ID Naselje</th>
                    <th>Naziv</th>
                    <th>Postanski Broj</th>
                    <th>Drzava</th>
                </tr>
            </thead>
            <tbody>
                {naseljeList.map(nas =>
                    <tr key={nas.idnaselje}>
                        <td></td>
                        <td>{nas.idnaselje}</td>
                        <td>{nas.naziv}</td>
                        <td>{nas.postanskiBroj}</td>
                        <td>{nas.drzava && nas.drzava.naziv}</td>
                        <td>
                            <a className="action" onClick={(id) => this.handleEdit(nas.idnaselje)}>Edit</a>  |
                            <a className="action" onClick={(id) => this.handleDelete(nas.idnaselje)}>Delete</a>
                        </td>
                    </tr>
                )}
            </tbody>
        </table>;
    }
}
export class NaseljeData {
    idnaselje: number = 0;
    naziv: string = "";
    postanskiBroj: string = "";
    drzava: DrzavaData = { iddrzava: 0, naziv: ""};
    drzavaid: number = 0;
}

export class DrzavaData {
    iddrzava: number = 0;
    naziv: string = "";
}

这是我想要动态显示的 AddNaselje 组件,即使上面的示例中仍然没有逻辑:

import * as React from 'react';
import { RouteComponentProps } from 'react-router';
import { Link, NavLink } from 'react-router-dom';
import { NaseljeData } from './FetchNaselje';
import { DrzavaData } from './FetchNaselje';

interface AddNaseljeDataState {
    title: string;
    loading: boolean;
    drzavaList: Array<any>;
    nasData: NaseljeData;
    drzavaId: number;
}

export class AddNaselje extends React.Component<RouteComponentProps<{}>, AddNaseljeDataState> {
    constructor(props) {
        super(props);

        this.state = { title: "", loading: true, drzavaList: [], nasData: new NaseljeData, drzavaId: -1 };
        fetch('api/Naselje/GetDrzavaList')
            .then(response => response.json() as Promise<Array<any>>)
            .then(data => {
                this.setState({ drzavaList: data });
            });

        var nasid = this.props.match.params["nasid"];
        // This will set state for Edit naselje  
        if (nasid > 0) {
            fetch('api/Naselje/Details/' + nasid)
                .then(response => response.json() as Promise<NaseljeData>)
                .then(data => {
                    this.setState({ title: "Edit", loading: false, nasData: data });
                });
        }
        // This will set state for Add naselje  
        else {
            this.state = { title: "Create", loading: false, drzavaList: [], nasData: new NaseljeData, drzavaId: -1 };
        }
        // This binding is necessary to make "this" work in the callback  
        this.handleSave = this.handleSave.bind(this);
        this.handleCancel = this.handleCancel.bind(this);
    }

    public render() {
        let contents = this.state.loading
            ? <p><em>Loading...</em></p>
            : this.renderCreateForm(this.state.drzavaList);
        return <div>
            <h1>{this.state.title}</h1>
            <h3>Naselje</h3>
            <hr />
            {contents}
        </div>;
    }

    // This will handle the submit form event.  
    private handleSave(event) {

        event.preventDefault();
        const data = new FormData(event.target);
        // PUT request for Edit naselje.  
        if (this.state.nasData.idnaselje) {
            fetch('api/Naselje/Edit', {
                method: 'PUT',
                body: data,
            }).then((response) => response.json())
                .then((responseJson) => {
                    this.props.history.push("/fetchnaselje");
                })
        }
        // POST request for Add naselje.  
        else {
            fetch('api/Naselje/Create', {
                method: 'POST',
                body: data,
            }).then((response) => response.json())
                .then((responseJson) => {
                    this.props.history.push("/fetchnaselje");
                })
        }
    }

    // This will handle Cancel button click event.  
    private handleCancel(e) {
        e.preventDefault();
        this.props.history.push("/fetchnaselje");
    }

    // Returns the HTML Form to the render() method.  
    private renderCreateForm(drzavaList: Array<any>) {
        return (
            <form onSubmit={this.handleSave} >
                <div className="form-group row" >
                    <input type="hidden" name="idnaselje" value={this.state.nasData.idnaselje} />
                </div>
                < div className="form-group row" >
                    <label className=" control-label col-md-12" htmlFor="Naziv">Naziv</label>
                    <div className="col-md-4">
                        <input className="form-control" type="text" name="naziv" defaultValue={this.state.nasData.naziv} required />
                    </div>
                </div >
                <div className="form-group row">
                    <label className="control-label col-md-12" htmlFor="PostanskiBroj" >Postanski broj</label>
                    <div className="col-md-4">
                        <input className="form-control" name="PostanskiBroj" defaultValue={this.state.nasData.postanskiBroj} required />
                    </div>
                </div>
                <div className="form-group row">
                    <label className="control-label col-md-12" htmlFor="Drzava">Država</label>
                    <div className="col-md-4">
                        <select className="form-control" data-val="true" name="drzavaid" defaultValue={this.state.nasData.drzava ? this.state.nasData.drzava.naziv : ""} required>
                            <option value="">-- Odaberite Državu --</option>
                            {drzavaList.map(drzava =>
                                <option key={drzava.iddrzava} value={drzava.iddrzava}>{drzava.naziv}</option>
                            )}
                        </select>
                    </div>
                </div >
                <div className="form-group">
                    <button type="submit" className="btn btn-default">Save</button>&nbsp;
                    <button className="btn" onClick={this.handleCancel}>Cancel</button>
                </div >
            </form >
        )
    }
}

我也不确定的一件事是组件的路由路径如果我在另一个组件中使用一个组件,我应该如何配置它们?

4

1 回答 1

1

确保您已安装所有类型npm install --save-dev @types/react-router

如果是这样,我想这只是 TypeScript/typings 编译问题。尝试将其RouteComponentProps<any>用作您的组件道具类型。(注意any代替{}

于 2018-10-12T11:51:28.257 回答