Состояние React ref равно null

Я хочу получить доступ к состоянию дочернего компонента с помощью ссылок, но состояние ссылки всегда равно нулю.

В моем приложении React у меня есть Editor (по сути, это форма), которая манипулирует своими состояниями, например. изменение значения, обновление. Редактор используется на нескольких страницах.

Editor.jsx

    export default class Editor extends React.Component {
        constructor(props) {
            super(props);
            this.state = {
                value1: null,
                ... other values 
            };
         }

         onValue1Change = (e) => {
            this.setState({value1: e.target.value});
         }

         onSave = (e) => {
            // save values
         }

         render() {
             return (
                <div>
                    <input value={this.state.value1} onChange={this.onValue1Change}/>
                    ... other input fields
                    <button onClick={this.onSave}>Save</button>
                </div>
             )
         }
     }

Теперь есть RegisterForm, который охватывает все поля в редакторе. Я сделал небольшое изменение в Editor, чтобы скрыть кнопку «Сохранить», чтобы я мог использовать ее в RegisterForm:

RegisterForm.jsx

    export default class RegisterForm extends React.Component {
        constructor(props) {
            super(props);
            this.state = {
                email: null,
                firstname: null,
                lastname: null
            };
            this.Editor = React.createRef();
        }

        onSave = (e) => {
            let childState = this.Editor.current.state;
            // childState is ALWAYS null!
        }

        render() {
            return (
                <div>
                    <input value={this.state.email} onChange={this.onEmailChange}/>
                    <input value={this.state.firstname} onChange={this.onFirstnameChange}/>
                    <input value={this.state.lastname} onChange={this.onLastnameChange}/>
                    ...
                    <Editor ref={this.Editor} showSave={false}/>
                    ...
                    <button onClick={this.onSave}>Save</button>
                </div>
            )
        }
    }

Оказывается, this.Editor.current.state всегда равно нулю.

У меня два вопроса.

  1. Почему this.Editor.current.state равно нулю?

  2. Если я хочу использовать реквизит, как мне изменить свой код? Например. Если бы я позволил RegisterForm передать реквизиты редактору, я бы представил что-то вроде этого:

Editor.jsx

    export default class Editor extends React.Component {
         // same constructor
         onValue1Change = (e) => {
            this.setState({value1: e.target.value}, () => {
                if(this.props.onValue1Change) this.props.onValue1Change(e);
            });
         }
         // same render
     }

RegisterForm.jsx

     export default class RegisterForm extends React.Component {
        constructor(props) {
            super(props);
            this.state = {
                email: null,
                firstname: null,
                lastname: null,
                value1: null,
            };
        }

        onValue1Change = (e) => {
            this.setState({value1: e.target.value});
        }

        render() {
            return (
                <div>
                    <Editor showSave={false} onValue1Change={this.onValue1Change}/>
                    ...
                </div>
            )
        }
    }

это делает дочерний компонент рендерингом дважды? Любые предложения о том, как улучшить его?


person yyc    schedule 30.03.2020    source источник


Ответы (1)


Вы передаете ссылку как реквизит компоненту <Editor/>, но после этого ничего с ним не делаете.

Например:

const FancyButton = React.forwardRef((props, ref) => (
  <button ref={ref} className="FancyButton">
    {props.children}
  </button>
));

// You can now get a ref directly to the DOM button:
const ref = React.createRef();
<FancyButton ref={ref}>Click me!</FancyButton>;

Получите реквизиты и ссылку через параметр обратного вызова forwardRef(), затем передайте ссылку дочернему узлу.

Это называется переадресация ссылок.

Я создал песочницу кода, чтобы вы могли ее протестировать!

person Al Duncanson    schedule 31.03.2020
comment
Спасибо, переадресация рефов устранила проблему. - person yyc; 01.04.2020