Обновите все дочерние компоненты реакции

У меня есть такой код:

<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>

Редактор имеет такую ​​функцию render():

    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 >

У меня есть такая функция в <List> onSelect

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

<Editor> покажет список из /api/customer с <List> и отправит выбранные значения в onSelect props, которые, в свою очередь, обновят все <Column> дочерние элементы. Данные соответствуют идентификатору столбца, например:

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

Этот метод, который я здесь выложил, работает только с детьми непосредственно под <Editor>, но не под <Group>.

Мой вопрос в том, как я могу выполнить глубокое обновление всех значений <Column> как дочерних элементов <Editor>, когда пользователь щелкнул значение в <List>. Я имею в виду, выполнить <Column> поиск по всем дочерним элементам и обновить все значения, независимо от того, где они находятся, если они находятся внутри тега <Editor>.

Любая помощь приветствуется. Спасибо


person Magician    schedule 25.11.2018    source источник
comment
Ничего не изменилось в <Group /> - нет причин для повторного рендеринга   -  person xadm    schedule 25.11.2018
comment
Я хочу изменить ‹Столбец /› внутри ‹Группы /›   -  person Magician    schedule 25.11.2018


Ответы (2)


<Group /> в качестве промежуточного «уровня» будет «блокировать распространение изменений» — этот компонент не «потребляет» какую-либо поддержку и, следовательно, не знает об изменениях.

Вы можете/нужно:

  • изменить структуру;
  • передать реквизит, который будет изменен (и принудительно обновит дочерние элементы);
  • использовать редукс;
  • использовать контекстный API.
person xadm    schedule 25.11.2018
comment
Ну, это не <Group /> как таковое, поскольку все, что находится внутри <Editor />, будет иметь значение <Column />, управляемое редактором. Таким образом, это может быть любой компонент, например <Tab /> или <Panel />, или любые компоненты макета пользовательского интерфейса или дополнительные компоненты. - person Magician; 26.11.2018

Хорошо... Это сломает Typescript, я не знаю, как правильно напечатать его в Typescript, но этот работает.

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;
    })
}
person Magician    schedule 25.11.2018