React条件渲染写法解析& React组件生命周期详解

30 阅读3分钟

🎯 条件渲染写法解析

📝 语法含义

{modalVisible && (
  <NewModal
    // props...
  />
)}

这是 短路求值(Short-circuit evaluation) 的JavaScript特性:

  • modalVisibletrue 时,执行右侧组件渲染
  • modalVisiblefalse 时,右侧不执行,返回 false(React会忽略)

🔄 等价写法对比

// 方式1: 短路求值 (推荐)
{modalVisible && <Modal />}

// 方式2: 三元运算符
{modalVisible ? <Modal /> : null}

// 方式3: if语句
{(() => {
  if (modalVisible) {
    return <Modal />;
  }
  return null;
})()}

// 方式4: 始终渲染,用CSS控制 (不推荐)
<Modal style={{ display: modalVisible ? 'block' : 'none' }} />

🚀 为什么要这样写?核心优势

1. 性能优化 - 避免不必要的DOM创建

// ❌ 不好的写法 - 组件始终存在
<Modal visible={modalVisible} />

// ✅ 好的写法 - 组件按需创建
{modalVisible && <Modal />}

2. 内存优化 - 组件完全卸载

// 当 modalVisible = false 时:
// - 组件实例被销毁
// - 占用的内存被释放
// - 事件监听器被清理
// - 定时器被清除

3. 生命周期控制

function Modal() {
  useEffect(() => {
    console.log('Modal mounted'); // 只在需要时执行
    
    return () => {
      console.log('Modal unmounted'); // 关闭时清理
    };
  }, []);
  
  return <div>Modal Content</div>;
}

🔄 React组件生命周期详解

📊 1. 函数组件生命周期

function MyComponent() {
  // 🔵 组件渲染阶段
  console.log('1. 函数组件执行');
  
  // 🟢 组件挂载后
  useEffect(() => {
    console.log('2. 组件挂载完成 (componentDidMount)');
    
    // 🔴 组件卸载前
    return () => {
      console.log('4. 组件卸载 (componentWillUnmount)');
    };
  }, []); // 空依赖数组
  
  // 🟡 组件更新后
  useEffect(() => {
    console.log('3. 组件更新完成 (componentDidUpdate)');
  }); // 无依赖数组,每次渲染都执行
  
  return <div>组件内容</div>;
}

📊 2. 类组件生命周期对比

class MyComponent extends React.Component {
  // 🔵 挂载阶段
  constructor(props) {
    super(props);
    console.log('1. constructor');
  }
  
  componentDidMount() {
    console.log('2. componentDidMount');
  }
  
  // 🟡 更新阶段
  componentDidUpdate() {
    console.log('3. componentDidUpdate');
  }
  
  // 🔴 卸载阶段
  componentWillUnmount() {
    console.log('4. componentWillUnmount');
  }
  
  render() {
    console.log('render');
    return <div>组件内容</div>;
  }
}

🎨 条件渲染的具体场景对比

🔥 场景1: 弹窗组件

// ❌ 始终渲染方式
function App() {
  const [modalVisible, setModalVisible] = useState(false);
  
  return (
    <div>
      <button onClick={() => setModalVisible(true)}>打开弹窗</button>
      <Modal 
        visible={modalVisible} 
        onClose={() => setModalVisible(false)}
      />  {/* 组件始终存在DOM中 */}
    </div>
  );
}

// ✅ 条件渲染方式
function App() {
  const [modalVisible, setModalVisible] = useState(false);
  
  return (
    <div>
      <button onClick={() => setModalVisible(true)}>打开弹窗</button>
      {modalVisible && (
        <Modal onClose={() => setModalVisible(false)} />
      )} {/* 组件按需创建/销毁 */}
    </div>
  );
}

📈 性能影响对比

// ❌ 始终渲染的问题
function ExpensiveModal() {
  useEffect(() => {
    // 这些操作始终执行,即使不可见
    const timer = setInterval(() => {
      console.log('定时任务执行');
    }, 1000);
    
    window.addEventListener('resize', handleResize);
    
    return () => {
      clearInterval(timer);
      window.removeEventListener('resize', handleResize);
    };
  }, []);
  
  return <div>复杂的弹窗内容</div>;
}

// ✅ 条件渲染的优势
function App() {
  return (
    <div>
      {/* 只有在需要时才创建ExpensiveModal */}
      {showModal && <ExpensiveModal />}
    </div>
  );
}

🛠️ 组件性能优化策略

🎯 1. 条件渲染优化

// ✅ 基础条件渲染
{show && <Component />}

// ✅ 复杂条件渲染
{isLoggedIn && hasPermission && <AdminPanel />}

// ✅ 使用 useMemo 优化复杂计算
const shouldShowComponent = useMemo(() => {
  return complexCalculation(data);
}, [data]);

{shouldShowComponent && <ExpensiveComponent />}

🎯 2. 组件懒加载

// ✅ React.lazy + Suspense
const LazyModal = React.lazy(() => import('./Modal'));

function App() {
  const [showModal, setShowModal] = useState(false);
  
  return (
    <div>
      {showModal && (
        <Suspense fallback={<div>Loading...</div>}>
          <LazyModal />
        </Suspense>
      )}
    </div>
  );
}

🎯 3. 状态提升优化

// ❌ 每个组件都管理自己的状态
function TodoItem({ todo }) {
  const [isEditing, setIsEditing] = useState(false);
  
  return (
    <div>
      {isEditing && <EditForm />} {/* 每个item都可能渲染EditForm */}
    </div>
  );
}

// ✅ 状态提升,全局只有一个编辑表单
function TodoList({ todos }) {
  const [editingId, setEditingId] = useState(null);
  
  return (
    <div>
      {todos.map(todo => (
        <TodoItem key={todo.id} todo={todo} />
      ))}
      {editingId && <EditForm todoId={editingId} />} {/* 全局唯一 */}
    </div>
  );
}

🎯 4. 使用 Portal 优化弹窗

import { createPortal } from 'react-dom';

function Modal({ children, onClose }) {
  useEffect(() => {
    const handleEscape = (e) => {
      if (e.key === 'Escape') onClose();
    };
    
    document.addEventListener('keydown', handleEscape);
    document.body.style.overflow = 'hidden'; // 防止滚动
    
    return () => {
      document.removeEventListener('keydown', handleEscape);
      document.body.style.overflow = 'unset';
    };
  }, [onClose]);
  
  // 渲染到body而不是父组件中
  return createPortal(
    <div className="modal-overlay" onClick={onClose}>
      <div className="modal-content" onClick={e => e.stopPropagation()}>
        {children}
      </div>
    </div>,
    document.body
  );
}

// 使用
{showModal && (
  <Modal onClose={() => setShowModal(false)}>
    <div>弹窗内容</div>
  </Modal>
)}

📊 不同场景的最佳实践

🔥 弹窗/模态框

// ✅ 推荐:条件渲染
{modalVisible && <Modal />}

🎨 显示/隐藏元素

// ✅ 简单显隐:CSS控制
<div style={{ display: isVisible ? 'block' : 'none' }}>

// ✅ 复杂组件:条件渲染
{isVisible && <ComplexComponent />}

📱 路由组件

// ✅ React Router已经做了条件渲染优化
<Routes>
  <Route path="/home" element={<Home />} />
  <Route path="/about" element={<About />} />
</Routes>

💡 总结

条件渲染 {condition && <Component />} 的核心价值在于:

  1. 性能优化:避免不必要的组件创建和渲染
  2. 内存管理:组件完全卸载,释放资源
  3. 生命周期控制:精确控制组件的创建和销毁时机
  4. 代码简洁:语法简单,语义清晰

这种写法特别适合重型组件弹窗复杂表单等场景,是React开发中的重要优化手段!