Дочерний компонент визуализируется, даже если он записан в память

#reactjs

#reactjs

Вопрос:

Дочерний компонент визуализируется, даже если его реквизиты не изменены. Ниже приведен родительский компонент

 import Child from "./Child";

function Parent({
  selected,
  show,
  setShow,
}) {
  const [isRunNow, setIsRunNow] = useState(true);
  const [isNotifyMe, setIsNotifyMe] = useState(false);

  
  const handleNotify = useCallback(() => {
    setIsNotifyMe(!isNotifyMe);
  }, [isNotifyMe]);

  const handleSchedule = useCallback(() => {
    setIsRunNow(!isRunNow);
  }, [isRunNow]);

  const WindowForm = () => {
    return (
      <div>
        <Row>
          <Col span={12}>
            <label className={styles.labelWeight}> Name : </label>
            <input
              type="text"
              value={selected.name}
              readOnly={true}
              className={styles.input}
            />
            <br></br>
            <br></br>
            <label className={styles.labelWeight}>Description : </label>
            <input
              type="text"
              value={selected.description}
              readOnly={true}
              className={styles.input}
            ></input>
            <br></br>
            <br></br>
            <input
              type="checkbox"
              name="runImm"
              id="runImm"
              checked={isRunNow}
              onChange={handleSchedule}
            ></input>
            <label> Schedule as soon as possible</label>
          </Col>
          <Col span={12}>
            <input
              type="checkbox"
              name="notifyProcess"
              id="notifyProcess"
              checked={isNotifyMe}
              onChange={handleNotify}
            ></input>
            <label> Notify me when this process ends</label>
            <br></br>
            <br></br>
            <label>Submission Notes : </label>
            <textarea
              name="notes"
              id="notes"
              rows="4"
              cols="50"
              disabled={!isNotifyMe}
            ></textarea>
          </Col>
        </Row>
        <Row>
          <Col span={24}>
            <Child isRunNow={isRunNow} />
          </Col>
        </Row>
      </div>
    );
  };

  return (
    <Modal
      visible={show}
      width={800}
      centered
      maskClosable={false}
      onCancel={() => setShow(false)}
      title="JKM"
      
    >
      <WindowForm />
    </Modal>
  );
}


 

Дочерний компонент выглядит следующим образом:

 import Uploader from "./Uploader";
import Downloader from "./Downloader";

const { TabPane } = Tabs;

const areEqual = (prevProps, nextProps) => {
  console.log("passed here"); // THIS IS NEVER LOGGED!!
  return true;
};

function Child({ isRunNow }) {
  console.log(
    `Rendering Childe component...isRunNow value : ${isRunNow}`
  );
  return (
    <div>
      <Tabs defaultActiveKey="ka">
        <TabPane tab="ka" key="ka">
           Panel
        </TabPane>
        <TabPane tab="sa" key="sa" disabled={isRunNow}>
          <Downloader />
        </TabPane>
        <TabPane tab="da" key="da">
          <Uploader />
        </TabPane>
      </Tabs>
    </div>
  );
}

export default React.memo(Child, areEqual);
 

Когда я устанавливаю или снимаю флажок Уведомлять меня, дочерний компонент дочернего компонента каждый раз повторно отображается. Кажется, что реквизиты не равны и, следовательно, их повторное воспроизведение. Я не мог понять, где что-то не так.
Пожалуйста, подскажите, где я делаю неправильно.

Комментарии:

1. это происходит каждый раз, когда вы нажимаете флажок с именем runImm?

2. Да, когда я устанавливаю или снимаю флажок с именем notifyProcess, дочерний компонент повторно отображается. Хотя флажок notifyProcess не имеет ничего общего со свойствами дочернего компонента

Ответ №1:

Я предлагаю вам отделить WindowForm от компонента, кажется, что это проблема. когда я использую его как компонент, memo начинает работать, я думаю, это связано с тем, что это функция, которая возвращает компонент, поэтому она отображает его, несмотря ни на что.

решение: переместите WindowForm за пределы компонента и создайте с ним новый, а затем вызовите его, и он будет работать нормально

 const WindowForm = () => {
    return (
      <div>
        <Row>
          <Col span={12}>
            <label className={styles.labelWeight}> Name : </label>
            <input
              type="text"
              value={selected.name}
              readOnly={true}
              className={styles.input}
            />
            <br></br>
            <br></br>
            <label className={styles.labelWeight}>Description : </label>
            <input
              type="text"
              value={selected.description}
              readOnly={true}
              className={styles.input}
            ></input>
            <br></br>
            <br></br>
            <input
              type="checkbox"
              name="runImm"
              id="runImm"
              checked={isRunNow}
              onChange={handleSchedule}
            ></input>
            <label> Schedule as soon as possible</label>
          </Col>
          <Col span={12}>
            <input
              type="checkbox"
              name="notifyProcess"
              id="notifyProcess"
              checked={isNotifyMe}
              onChange={handleNotify}
            ></input>
            <label> Notify me when this process ends</label>
            <br></br>
            <br></br>
            <label>Submission Notes : </label>
            <textarea
              name="notes"
              id="notes"
              rows="4"
              cols="50"
              disabled={!isNotifyMe}
            ></textarea>
          </Col>
        </Row>
        <Row>
          <Col span={24}>
            <Child isRunNow={isRunNow} />
          </Col>
        </Row>
      </div>
    );
  };
 

этот компонент и его состояние преобразуйте в новый компонент, и все начнет работать

Комментарии:

1. Спасибо. Это сработало. Но до сих пор неясно, как сработало перемещение компонента наружу. Любые комментарии были бы полезны для понимания проблемы.

2. ну, я сам не уверен, я думаю, это потому, что вы отправляете функцию, которая повторяется каждый раз, когда вы повторно изменяете компонент по изменению и значению, затем она снова и снова печатает функцию, независимо от заметки. возможно, вы можете попробовать использовать useCallback

3. @BNK после небольшого чтения это произошло потому, что вы отправляете функцию, которая повторяется каждый раз, когда вы меняете состояние. в отличие от usecallback, который блокирует эти данные, если они не соответствуют зависимостям