欢迎扫码,加作者微信

React18入门到精通教程

2023-02-21 18:01:52
2025-06-01 21:18:20

JSX实现列表渲染

使用map()方法遍历数组,必须添加key属性提高性能

jsx 复制代码
const songs = [
  { id: 1, name: "helo1" },
  { id: 2, name: "helo2" },
  { id: 3, name: "helo3" },
];

function App() {
  return (
    <div>
      <ul>
        {songs.map((song) => (
          // 关键:添加唯一key标识符(避免使用索引)
          <li key={song.id}>  
            {song.id}-{song.name}
          </li>
        ))}
      </ul>
    </div>
  );
}

最佳实践:

  1. 使用<ul>包裹列表项
  2. key应使用稳定唯一标识(如ID),避免数组索引
  3. 空列表处理:{songs.length > 0 && ...}{songs.map(...) || <EmptyView/>}

JSX实现条件渲染

简单逻辑

jsx 复制代码
// 三元表达式
{isLoggedIn ? <Dashboard /> : <LoginForm />}

// 逻辑短路
{hasNotification && <NotificationBadge count={5} />}

// 空值处理
{userProfile?.avatar || <DefaultAvatar />}

复杂逻辑

jsx 复制代码
const renderContent = (type) => {
  switch(type) {
    case 'success': 
      return <SuccessAlert />;
    case 'error':
      return <ErrorAlert />;
    default:
      return <InfoAlert />;
  }
}

function App() {
  return (
    <div className="container">
      {renderContent(status)}
      
      {/* 另一种模式:立即执行函数 */}
      {(() => {
        if (isLoading) return <Spinner />;
        if (isEmpty) return <EmptyState />;
        return <DataTable />;
      })()}
    </div>
  )
}

JSX样式处理

行内样式

jsx 复制代码
// 直接对象
<div style={{ 
  color: 'white', 
  backgroundColor: 'teal',
  padding: '1rem'
}}>

// 样式对象复用
const alertStyle = {
  padding: '15px',
  borderRadius: '4px',
  margin: '10px 0'
};

function Alert({ type }) {
  return (
    <div style={{
      ...alertStyle,  // 扩展运算符合并样式
      background: type === 'error' ? '#f8d7da' : '#d4edda'
    }}>
      {message}
    </div>
  )
}

类名控制(推荐)

css 复制代码
/* styles.module.css */
.card {
  border: 1px solid #ddd;
  border-radius: 8px;
  padding: 20px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

.highlight {
  background-color: #ffffe0;
}
jsx 复制代码
import styles from './styles.module.css';

function ProductCard({ featured }) {
  return (
    <div className={`${styles.card} ${featured ? styles.highlight : ''}`}>
      {/* 内容 */}
    </div>
  );
}

React 18新特性

并发模式(Concurrent Mode)

jsx 复制代码
import { startTransition } from 'react';

// 非紧急状态更新
function handleSearch(query) {
  startTransition(() => {
    setSearchQuery(query); // 可中断的渲染
  });
}

自动批处理(Automatic Batching)

jsx 复制代码
// React 17及之前:两次渲染
// React 18:自动批处理,一次渲染
function handleClick() {
  setCount(c => c + 1);
  setFlag(f => !f);
}

Redux状态管理(现代写法)

安装依赖

bash 复制代码
npm install @reduxjs/toolkit react-redux

创建Store

js 复制代码
// store.js
import { configureStore, createSlice } from '@reduxjs/toolkit';

const counterSlice = createSlice({
  name: 'counter',
  initialState: { value: 0 },
  reducers: {
    increment: state => { state.value += 1 },
    decrement: state => { state.value -= 1 },
    incrementByAmount: (state, action) => {
      state.value += action.payload
    }
  }
});

// 异步操作示例
export const fetchUserData = () => async (dispatch) => {
  const response = await fetch('/api/user');
  dispatch(setUser(await response.json()));
};

export const store = configureStore({
  reducer: {
    counter: counterSlice.reducer,
    // 其他reducer...
  }
});

export const { increment, decrement } = counterSlice.actions;

组件集成

jsx 复制代码
// index.js
import { Provider } from 'react-redux';
import { store } from './store';

root.render(
  <Provider store={store}>
    <App />
  </Provider>
);

// Counter.js
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement } from './store';

function Counter() {
  const count = useSelector(state => state.counter.value);
  const dispatch = useDispatch();

  return (
    <div>
      <button onClick={() => dispatch(decrement())}>-</button>
      <span>{count}</span>
      <button onClick={() => dispatch(increment())}>+</button>
    </div>
  );
}

最佳实践总结

  1. 组件设计:遵循单一职责原则,拆分智能组件(容器组件)和展示组件
  2. 状态管理
    • 局部状态用useState/useReducer
    • 全局共享状态用Redux
    • 避免过度使用状态提升
  3. 性能优化
    • 使用React.memo记忆组件
    • 使用useCallback/useMemo避免不必要的重渲染
    • 虚拟化长列表(react-window)
  4. Hooks规范
    • 避免在循环/条件中使用Hook
    • 自定义Hook以use前缀命名
  5. TypeScript集成
    tsx 复制代码
    interface UserCardProps {
      name: string;
      age: number;
      onSelect: (id: string) => void;
    }
    
    const UserCard: React.FC<UserCardProps> = ({ name, age }) => (
      <div>{name} ({age})</div>
    )

下面为您完善教程,增加React路由和生命周期相关内容:

React路由管理(React Router v6)

安装与基础配置

bash 复制代码
npm install react-router-dom@6

路由基础结构

jsx 复制代码
// index.js
import { BrowserRouter } from 'react-router-dom';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>
);

// App.js
import { Routes, Route, Link } from 'react-router-dom';

function App() {
  return (
    <div>
      <nav>
        <Link to="/">首页</Link>
        <Link to="/about">关于</Link>
        <Link to="/users">用户列表</Link>
      </nav>
      
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="/users" element={<UserList />} />
        <Route path="/users/:id" element={<UserDetail />} />
        <Route path="*" element={<NotFound />} />
      </Routes>
    </div>
  );
}

嵌套路由

jsx 复制代码
// Dashboard.js
import { Outlet } from 'react-router-dom';

function Dashboard() {
  return (
    <div>
      <h2>仪表盘</h2>
      <Outlet /> {/* 子路由渲染位置 */}
    </div>
  );
}

// 路由配置
<Routes>
  <Route path="/dashboard" element={<Dashboard />}>
    <Route index element={<DashboardHome />} />
    <Route path="settings" element={<DashboardSettings />} />
    <Route path="analytics" element={<DashboardAnalytics />} />
  </Route>
</Routes>

编程式导航

jsx 复制代码
import { useNavigate, useParams, useLocation } from 'react-router-dom';

function UserCard({ user }) {
  const navigate = useNavigate();
  
  return (
    <div onClick={() => navigate(`/users/${user.id}`)}>
      {user.name}
    </div>
  );
}

function UserDetail() {
  const { id } = useParams(); // 获取URL参数
  const location = useLocation(); // 获取位置对象
  
  return (
    <div>
      <h2>用户ID: {id}</h2>
      <p>当前路径: {location.pathname}</p>
    </div>
  );
}

路由守卫(认证保护)

jsx 复制代码
import { Navigate } from 'react-router-dom';

function ProtectedRoute({ children }) {
  const { isAuthenticated } = useAuth();
  
  if (!isAuthenticated) {
    return <Navigate to="/login" replace />;
  }
  
  return children;
}

// 使用
<Route 
  path="/dashboard" 
  element={
    <ProtectedRoute>
      <Dashboard />
    </ProtectedRoute>
  } 
/>

React生命周期

类组件生命周期方法

jsx 复制代码
class LifecycleDemo extends React.Component {
  // 1. 初始化阶段
  constructor(props) {
    super(props);
    this.state = { count: 0 };
    console.log('Constructor');
  }

  // 2. 挂载阶段
  componentDidMount() {
    console.log('Component did mount');
    // 适合进行API调用、事件订阅
    this.timer = setInterval(() => {
      this.setState(prev => ({ count: prev.count + 1 }));
    }, 1000);
  }

  // 3. 更新阶段
  shouldComponentUpdate(nextProps, nextState) {
    console.log('Should component update?');
    return nextState.count !== this.state.count;
  }

  componentDidUpdate(prevProps, prevState) {
    console.log('Component did update');
  }

  // 4. 卸载阶段
  componentWillUnmount() {
    console.log('Component will unmount');
    // 清理操作
    clearInterval(this.timer);
  }

  render() {
    console.log('Render');
    return <div>Count: {this.state.count}</div>;
  }
}

函数组件生命周期(Hooks实现)

jsx 复制代码
import { useState, useEffect } from 'react';

function FunctionLifecycle() {
  const [count, setCount] = useState(0);
  const [data, setData] = useState(null);

  // 相当于componentDidMount + componentDidUpdate
  useEffect(() => {
    console.log('每次渲染后执行');
  });

  // 相当于componentDidMount
  useEffect(() => {
    console.log('组件挂载后执行');
    
    // 数据获取
    fetch('/api/data')
      .then(res => res.json())
      .then(setData);
    
    // 相当于componentWillUnmount
    return () => {
      console.log('组件卸载前执行');
    };
  }, []); // 空依赖数组

  // 依赖变化时执行
  useEffect(() => {
    console.log('count变化时执行:', count);
    
    document.title = `Count: ${count}`;
    
    return () => {
      console.log('清理count效果');
    };
  }, [count]); // count依赖

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(c => c + 1)}>增加</button>
      {data && <pre>{JSON.stringify(data, null, 2)}</pre>}
    </div>
  );
}

生命周期阶段对比

阶段 类组件方法 函数组件Hook
挂载 constructor useState初始化
render 函数体执行
componentDidMount useEffect(() => {}, [])
更新 shouldComponentUpdate React.memo, useMemo
render 函数体执行
componentDidUpdate useEffect(() => {})
卸载 componentWillUnmount useEffect返回函数
错误处理 componentDidCatch 暂无直接等效,需错误边界组件

现代React开发建议

  1. 优先使用函数组件+Hooks

    • 90%的场景可替代类组件
    • 更简洁的代码结构
    • 更好的逻辑复用
  2. 关键生命周期替代

    • componentDidMountuseEffect(() => {}, [])
    • componentDidUpdateuseEffect(() => {}) 或带依赖的 useEffect
    • componentWillUnmountuseEffect(() => { return cleanup }, [])
    • shouldComponentUpdateReact.memouseMemo
  3. 数据获取最佳实践

jsx 复制代码
useEffect(() => {
  let isMounted = true;
  
  const fetchData = async () => {
    try {
      const result = await api.getData();
      if (isMounted) setData(result);
    } catch (error) {
      if (isMounted) setError(error);
    }
  };
  
  fetchData();
  
  return () => {
    isMounted = false; // 避免组件卸载后设置状态
  };
}, []);

路由与生命周期整合示例

jsx 复制代码
function UserProfile() {
  const { id } = useParams();
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    let isActive = true;
    
    const fetchUser = async () => {
      try {
        setLoading(true);
        const data = await fetchUserById(id);
        if (isActive) {
          setUser(data);
          setLoading(false);
        }
      } catch (error) {
        if (isActive) {
          setError(error.message);
          setLoading(false);
        }
      }
    };
    
    fetchUser();
    
    return () => {
      isActive = false; // 清理效果
    };
  }, [id]); // id变化时重新获取

  if (loading) return <Spinner />;
  
  return (
    <div>
      <h2>{user.name}</h2>
      <p>Email: {user.email}</p>
    </div>
  );
}

完整项目结构建议

复制代码
src/
├── components/      # 通用UI组件
├── pages/           # 页面组件
├── layouts/         # 布局组件
├── hooks/           # 自定义Hooks
├── store/           # Redux状态
│   ├── slices/
│   └── store.js
├── services/        # API服务
├── routers/         # 路由配置
├── utils/           # 工具函数
├── assets/          # 静态资源
└── App.js           # 主应用组件

这些新增内容涵盖了React路由的现代用法(v6版本)以及React生命周期的详细解释,包括类组件和函数组件的实现方式对比。同时还提供了路由与生命周期整合的实际示例,帮助开发者理解如何在真实项目中应用这些概念。

目录

运营需要亿点资金维持,您的支持,是小白龙创作的动力!!!

昵称
留言
赞赏金额
暂无评论,欢迎留下你的评论
暂无评论,欢迎留下你的评论