Search code examples
reactjstypescript3.0

Update all react children components


I have a code like this:

<Editor source="/api/customer" onCreate={this.debugChange} onDelete={this.debugChange} onUpdate={this.debugChange}>
    <Group title="Address">
        <Column id="id" label="ID" default={0} readonly />
        <Column id="name" label="name" default="" />
        <Column id="address" label="Address" default="" />
        <Column id="country" label="Country" default={currentCountry} readonly source="/api/country" idfield="id" captionField="name" />
    </Group>
    <Group title="Payment">
        <Column id="tax" label="TaxType" default={0} source="/api/taxtype" idfield="id" captionField="name" />
        <Column id="bank" label="Bank" default="" source="/api/banks" idfield="id" captionField="bank"/>
        <Column id="account" label="Account Number" default="" />
    </Group>
</Editor>

Editor has a render() function like this:

    let components = React.Children.map(this.props.children, (child) => {
        return <Column {...child.props} default={row[child.props.id]} onChange={this.onChange.bind(this)} />
    })

    return <div className="hx-editor">
        <div className="hx-editor-list">
            <List id={this.props.id + "-list"} source={this.props.source}
                singleShow captionField={this.caption.bind(this)}
                groupfn={this.props.group} onSelect={this.onSelect.bind(this)} />
        </div>
        <form name={"hx-form-" + this.props.id} className="hx-form">
            {components}
            {buttons}
        </form>
    </div >

I have the function like this at <List>'s onSelect

private onSelect(id: string, data: T) {
    this.setState({
        currentRow: data,
        modifiedRow: data
    })
}

<Editor> will show a list from /api/customer with <List>, and send the selected values to onSelect props, which in turn update all <Column> children. The data corresponds with column's id, such as:

data = [{
    id: 0,
    name: 'My Customer',
    address: 'This is Address',
    country: 'US',
    tax: '010',
    bank: 'HSBC',
    account:: '89238882839304'
}, ... ]

This method that I put here, only works with children directly under <Editor>, but not under <Group>.

My question is, how can I do deep update of all values of <Column> as <Editor>'s children when a user clicked on a value in <List>. I mean, perform <Column> search through all children, and update all values, no matter where they are, as long as within <Editor> tag.

Any help is appreciated. Thank you


Solution

  • Ok... This will break Typescript, I don't know how to type it in Typescript properly, but this one works.

    private deepColumn(children: React.ReactNode) => any) {
        return React.Children.map(children, child => {
            if (child.props.children) {
                child = React.cloneElement(child, {
                    children: this.deepColumn(child.props.children)
                })
            }
            if (child.type.name == "Column") {
                return <Column {...child.props} default={this.default} onChange={this.onChange.bind(this)} />
            } else return child;
        })
    }