Прекратить повторную визуализацию родительских компонентов. Только повторный рендеринг дочернего компонента - PullRequest
0 голосов
/ 19 июня 2019

У меня есть поле React-Select внутри поля Formik, которое при выборе элемента в раскрывающихся меню переопределяет все родительские компоненты. Это самый глубокий дочерний компонент, доступный в контейнере.

И это заново отображает 4 Родителя. Что является своего рода проблематичным. Я хочу ограничить повторное отображение компонента только для себя.

The above happens because each Child Process passes
props to the Container, which is the master form.
And onSubmit it takes all the info(props) and makes the API Call.

Я пытался сделать это с shouldComponentUpdate, но не повезло. Я пытался сделать это с SetState, но это упало в воду, так как я не мог заставить его работать (получил кучу ошибок).

- TLDR - ЭТА ПРОБЛЕМА: Сделайте Компонент, сохраняющий рендеринг только для себя. Внешние компоненты, используемые в нем Formik и React-Select.

Вот код для этого:

            <div className="w-50">
              <Field
                name={`${keyField}.${index}.permissions`}
                render={({ field: { value, name }, form: { setFieldValue, setFieldTouched } }) => (
                  <div>
                    <label htmlFor="namespace-permissions" className="font-weight-medium">
                      Permissions in Namespace <Asterisk />
                    </label>
                    <Select
                      isMulti
                      closeMenuOnSelect={false}
                      id="namespace-permissions"
                      defaultValue={convertNamespaceToDefaultValue(
                        dependencies.namespacePermissions,
                        value
                      )}
                      options={convertNamespaceToSelect(dependencies.namespacePermissions)}
                      onChangeCallback={values => {
                        setFieldValue(name, convertSelectToNamespacesData(values));
                        setFieldTouched(name, true);
                      }}
                    />
                    <ErrorMessage name={name} component={FormErrorMessage} />
                  </div>
                )}
              />
            </div>

Опора dependacies - это то, что делает путешествие вверх по дереву, к мастер-форме Реквизит, и перерисовывает все Дерево Компонентов. Это также связано с другим вопросом, который у меня был вчера, о том, что closeMenuOnSelect={false} реагирующего выбора работает неправильно

^ Вот почему это происходит. Спасибо ..

1 Ответ

1 голос
/ 19 июня 2019

Я не знаю, как вы могли бы сделать это с библиотеками, которые вы используете.Но когда я не хочу, чтобы мои компоненты рендерились без необходимости, я использую React.memo, это будет поверхностное сравнение объекта props и решит, нужно ли обновлять.

Из React DOCS

БЕЗ РЕАГИРОВАНИЯ MEMO

function App() {
  return(
    <Parent1/>
  );
}

function Parent1(props) {
  console.log('Rendering Parent1...');

  const [parentState,setParentState] = React.useState(true);

  return(
    <Parent2
      setParentState={setParentState}
    />
  );
}

function Parent2(props) {

  console.log('Rendering Parent2...');

  return(
    <Child
      setParentState={props.setParentState}
    />
  );
}

function Child(props) {
  
  console.log('Rendering Child...');
  
  return(
    <button onClick={()=>props.setParentState((prevState)=>!prevState)}>Update ParentState</button>
  );
}

ReactDOM.render(<App/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>

С REACT.MEMO

function App() {
  return(
    <Parent1/>
  );
}

function Parent1(props) {
  console.log('Rendering Parent1...');

  const [parentState,setParentState] = React.useState(true);

  return(
    <Parent2
      setParentState={setParentState}
    />
  );
}


const Parent2 = React.memo(function Parent2(props) {

  console.log('Rendering Parent2...');

  return(
    <Child
      setParentState={props.setParentState}
    />
  );
}
);

const Child = React.memo(function Child(props) {
  
  console.log('Rendering Child...');
  
  return(
    <button onClick={()=>props.setParentState((prevState)=>!prevState)}>Update ParentState</button>
  );
}
);

ReactDOM.render(<App/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>
...