Реагирование: Как реорганизовать это, чтобы предотвратить повторный рендеринг и инкапсулировать его в компонент, который имеет значение? - PullRequest
0 голосов
/ 15 января 2020

Я использую родительский компонент, который определяет useState для управления сообщениями, которые я хочу отображать на панели

Примерно так (псевдокод)

const Com1 = ({message, setMessage}) => {
  useEffect(() => {
    const fun = async () => {
      if (message) {
        await wait(4000)
        setMessage('')
      }
    }

    const stillMounted = { value: true }
    fun(stillMounted)
    return () => (stillMounted.value = false)
  }, [message])

  return <Message>{message}</Message>
}

const Com2 = ({setMessage}) => {
  if (condition) setMessage('important message`)
  return <></>
}

const Parent = () => {
  const [message, setMessage] = useState('')
  return (
  <>
    <Com1 message={message} setMessage={setMessage} />
    <Others1 />
    <Others2 />
    <Com2 setMessage={setMessage} />
  </>
  )
}

проблема в том, что я хотел бы, чтобы перекрашивался только компонент <Com1> -> <Message>, но я перекрашивался также <Others>

Это прискорбно, потому что, если я пишу числа в элементах <input>, когда он получает перекрашивается Я теряю свои номера, когда они возвращаются к своим исходным значениям

Как я мог структурировать свой код, чтобы избежать этого?

in one image

Ответы [ 2 ]

0 голосов
/ 15 января 2020

Это действительно работает, поскольку компоненты, которые вы не хотите повторно визуализировать, определяются вне родительского компонента.

В этом случае этот код и окно отображают проблему только потому, что <Others> определены внутри основной компонент

Если я переместу этот компонент наружу, то он не будет перерисован

https://codesandbox.io/s/laughing-swartz-ql8j2?fontsize=14&hidenavigation=1&theme=dark

(код, не самый простой один, но, выясняя, что происходит, я воспроизвел как можно больше своего собственного кода)

import React, { useState, useEffect, useRef, forwardRef } from "react";
import styled from "@emotion/styled";

export const wait = ms =>
  new Promise((res, rej) => setTimeout(() => res("timed"), ms));

const useCombinedRefs = (...refs) => {
  const targetRef = useRef();

  useEffect(() => {
    refs.forEach(ref => {
      if (!ref) return;

      if (typeof ref === "function") ref(targetRef.current);
      else ref.current = targetRef.current;
    });
  }, [refs]);

  return targetRef;
};

const Com1 = ({ message, setMessage }) => {
  useEffect(() => {
    const fun = async () => {
      if (message) {
        await wait(4000);
        setMessage("");
      }
    };

    const stillMounted = { value: true };
    fun(stillMounted);
    return () => (stillMounted.value = false);
  }, [message]);

  return <Message show={message ? 1 : 0}>{message}</Message>;
};

const Com2 = ({ setMessage }) => {
  const test = async () => {
    await wait(4000);
    setMessage("important message");
  };
  useEffect(() => {
    test();
  }, []);
  return <></>;
};

export default function App() {
  const [message, setMessage] = useState("");
  const myRef1 = useRef();
  const myRef2 = useRef();

  const Others = forwardRef((props, ref) => {
    const innerRef = useRef();
    const combinedRef = useCombinedRefs(ref, innerRef);

    const write = () => (combinedRef.current.value = 3);

    return <input ref={combinedRef} onClick={write} />;
  });

  return (
    <>
      <Com1 message={message} setMessage={setMessage} />
      <Others ref={myRef1} />
      <Others ref={myRef2} />
      <Com2 setMessage={setMessage} />
    </>
  );
}

const Message = styled.div`
  background: ${props => (props.show ? "#ababab" : "#fff0")};
  width: 100%;
  border-radius: 8px;
  color: #fff;
  padding: 10px;
  margin: 10px 0px;
  transition: background 0.2s ease-in;
  min-height: 50px;
`;
0 голосов
/ 15 января 2020

Conponent отображает или повторно отображает где-то внутри этого компонента, в то время как вы не опубликовали <Others> исходный код.

С ним нельзя управлять извне, IFAIK.

React действительно имеет инструмент управлять повторным рендерингом, как shouldComponentUpdate, React.memo, React.PureComponent - так что вы можете выбрать один (внутри <Others>).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...