一尘不染

如何在反应中正确有条件地渲染子组件

javascript

我有以下组件:(AddBookPanel 包含 AddBookForm)

我需要能够在单击“AddBookButton”时显示表单,并且还能够在单击“x”按钮时隐藏表单(AddBookForm 组件中的 img),但是该组件似乎没有加载正确地,这里有什么问题?你认为最好的组织方式是什么?

import { AddBookButton } from './AddBookButton';
import { AddBookForm } from './AddBookForm';
import { useState } from 'react';

export const AddBookPanel = () => {
  const [addBookPressed, setAddBookPressed] = useState(false);

  return (
    <div>
      <div onClick={() => setAddBookPressed(!addBookPressed)}>
        <AddBookButton />
      </div>
      <AddBookForm initialFormActive={addBookPressed} />
    </div>
  );
};
import { useState } from 'react';

interface AddBookFormProps {
  initialFormActive: boolean;
}

export const AddBookForm: React.FC<AddBookFormProps> = ({
  initialFormActive,
}) => {
  const [isFormActive, setIsFormActive] = useState(initialFormActive);

  return (
    <>
      {isFormActive && (
        <div className="fixed box-border h-2/3 w-1/3 border-4 left-1/3 top-24 bg-white border-slate-600 shadow-xl">
          <div className="flex justify-between bg-slate-400">
            <div>
              <p className="text-4xl my-5 mx-6">Add a new Book</p>
            </div>
            <div className="h-16 w-16 my-3 mx-3">
              <button onClick={() => setIsFormActive(!isFormActive)}>
                <img
                  src="https://upload.wikimedia.org/wikipedia/commons/thumb/a/a0/OOjs_UI_icon_close.svg/1200px-OOjs_UI_icon_close.svg.png"
                  alt="close-button"
                  className="object-fit"
                ></img>
              </button>
            </div>
          </div>

          <div className="flex-col">
            <div className="flex justify-between my-10 ml-5 text-xl">
              <input type="text" placeholder="book name"></input>
            </div>
          </div>
        </div>
      )}
    </>
  );
};

阅读 78

收藏
2022-07-26

共1个答案

一尘不染

你总是在渲染AddBookForm. 这意味着在初始渲染中useState使用false. 由于您从不调用setIsFormActive它,因此现在卡在“不渲染”状态。

只是不要直接使用useState和使用该属性initialFormActive。也许将其重命名为isFormActive. 让父处理状态变化。

import { AddBookButton } from './AddBookButton';
import { AddBookForm } from './AddBookForm';
import { useState } from 'react';

export const AddBookPanel = () => {
  const [addBookPressed, setAddBookPressed] = useState(false);

  return (
    <div>
      <div onClick={() => setAddBookPressed(!addBookPressed)}>
        <AddBookButton />
      </div>
      <AddBookForm initialFormActive={addBookPressed} onClose={() => setAddBookPressed(false)} />
    </div>
  );
};
import { useState } from 'react';

interface AddBookFormProps {
  initialFormActive: boolean;
  onColse: () => void;
}

export const AddBookForm: React.FC<AddBookFormProps> = ({
  initialFormActive,
  onClose,
}) => {
  // const [isFormActive, setIsFormActive] = useState(initialFormActive); don't use this frozen state, allow the parent to control visibility

  return (
    <>
      {initialFormActive && (
        <div className="fixed box-border h-2/3 w-1/3 border-4 left-1/3 top-24 bg-white border-slate-600 shadow-xl">
          <div className="flex justify-between bg-slate-400">
            <div>
              <p className="text-4xl my-5 mx-6">Add a new Book</p>
            </div>
            <div className="h-16 w-16 my-3 mx-3">
              <button onClick={() => onClose()}>
                <img
                  src="https://upload.wikimedia.org/wikipedia/commons/thumb/a/a0/OOjs_UI_icon_close.svg/1200px-OOjs_UI_icon_close.svg.png"
                  alt="close-button"
                  className="object-fit"
                ></img>
              </button>
            </div>
          </div>

          <div className="flex-col">
            <div className="flex justify-between my-10 ml-5 text-xl">
              <input type="text" placeholder="book name"></input>
            </div>
          </div>
        </div>
      )}
    </>
  );
};
2022-07-26