Реагировать - обновлять состояние в дочернем компоненте при изменении родительского - PullRequest
1 голос
/ 19 сентября 2019

У меня есть простое приложение с двумя реагирующими компонентами:

  1. vacancies.jsx - список вакансий
  2. counter.jsx - показывает количество вакансий от vacancies.jsx

Когда приложение загружает, счетчик показывает правильное количество вакансий, но когда я начинаю добавлять / удалять вакансии в vacancies.jsx, количество остается неизменным.

vacancies.jsx:

export class Vacancy extends React.Component {

    constructor(props) {

        super(props);

        this.state = { vacancies: [], loading: true, title:"" };

        fetch('/api/Vacancy/Vacancies')
            .then(response => response.json())
            .then(data => {
                this.setState({ vacancies: data, loading: false });
            });
    }

    delete(id) {

        var vacancies = this.state.vacancies;

        this.setState(
            {
                vacancies: this.state.vacancies.filter((v) => {
                    return (v.id != id);
                })
            });

    }

    loadVacancies(vacancies) {
        return (
            <table className='table table-striped'>
                <thead>
                    <tr>
                        <th>Title</th>
                        <th>Min Salary</th>
                        <th>Max Salary</th>
                    </tr>
                </thead>
                <tbody>
                    {vacancies.map(v =>
                        <tr key={v.id}>
                            <td>{v.title}</td>
                            <td>{v.currency} {v.minSalary}</td>
                            <td>{v.currency} {v.maxSalary}</td>
                            <td>
                                <a href="#" onClick={(id) => this.delete(v.id)}>Delete</a>
                            </td>
                        </tr>
                    )}
                </tbody>
            </table>
        );
    }

    render() {

        let contents = this.state.loading
            ? <p><em>Loading...</em></p>
            : this.loadVacancies(this.state.vacancies);

        return (
            <div>
                {contents}
            </div>
        );
    }
}

const containerElement = document.getElementById('content');
ReactDOM.render(<Vacancy />, containerElement);

counter.jsx

import { Vacancy } from "./vacancies";

export class Counter extends Vacancy {

    constructor(props) {

        super(props);
    }

    render() {

        return (
            <div>
                <h1>Items:{this.state.vacancies.length}</h1>
            </div>
        );
    }
}

ReactDOM.render(<Counter />, document.getElementById('counter'));

UI: enter image description here

1 Ответ

2 голосов
/ 19 сентября 2019

По словам команды реагирования, они рекомендуют использовать композицию вместо наследования:

В React имеется мощная модель композиции, и мы рекомендуем использовать композицию вместо наследования для повторного использования кода между компонентами.

И

В Facebook мы используем React в тысячах компонентов, и мы не нашли случаев использования, в которых мы бы рекомендовали создавать иерархии наследования компонентов.

https://reactjs.org/docs/composition-vs-inheritance.html

Итак, на основе вашего кода, воссоздайте свой Counter компонент следующим образом:

export const Counter = props => {
    return (
        <div>Items: {props.items}</div>
    );
};

Затем просто измените свой Vacancies компонент, включая новый Counter компонент там:

loadVacancies(vacancies) {
    return (

        <Counter items={this.state.vacancies.length} />

        <table className='table table-striped'>
            <thead>
                <tr>
                    <th>Title</th>
                    <th>Min Salary</th>
                    <th>Max Salary</th>
                </tr>
            </thead>
            <tbody>
                {vacancies.map(v =>
                    <tr key={v.id}>
                        <td>{v.title}</td>
                        <td>{v.currency} {v.minSalary}</td>
                        <td>{v.currency} {v.maxSalary}</td>
                        <td>
                            <a href="#" onClick={(id) => this.delete(v.id)}>Delete</a>
                        </td>
                    </tr>
                )}
            </tbody>
        </table>
    );
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...