React入门实战:构建一个天气查询应用(2025最新)

引言

React作为当今最流行的前端框架之一,其组件化思想和声明式编程模式彻底改变了现代Web开发。本教程将通过构建一个完整的天气查询应用,系统性地讲解React的核心概念和最佳实践。项目将覆盖React 18最新特性,使用Vite构建工具,并整合现代前端开发工作流。

项目概览

应用功能需求:

城市天气实时查询
温度单位切换(℃/℉)
最近查询历史记录
天气图标动态展示
响应式布局适配
加载状态与错误处理

技术栈:

React 18(函数组件 + Hooks)
React Router v6
Axios
OpenWeatherMap API
CSS Modules
Vite 5

前置知识准备

ES6+基础(箭头函数、解构赋值、模块化)
基础HTML/CSS
npm/yarn基础用法
REST API概念
项目搭建

npm create vite@latest weather-app -- --template react
cd weather-app
npm install react-router-dom axios react-icons

核心功能实现

  1. 应用路由配置
// src/main.jsx
import { createRoot } from 'react-dom/client'
import { BrowserRouter } from 'react-router-dom'
import App from './App'

createRoot(document.getElementById('root')).render(
  <BrowserRouter>
    <App />
  </BrowserRouter>
)
  1. 全局状态管理(Context API)
// src/context/WeatherContext.jsx
import { createContext, useContext, useReducer } from 'react'

const WeatherContext = createContext()

const initialState = {
  unit: 'metric',
  history: [],
  loading: false,
  error: null
}

const reducer = (state, action) => {
  switch (action.type) {
    case 'SET_UNIT':
      return { ...state, unit: action.payload }
    case 'ADD_HISTORY':
      return { ...state, history: [action.payload, ...state.history.slice(0, 4)] }
    case 'SET_LOADING':
      return { ...state, loading: action.payload }
    case 'SET_ERROR':
      return { ...state, error: action.payload }
    default:
      return state
  }
}

export const WeatherProvider = ({ children }) => {
  const [state, dispatch] = useReducer(reducer, initialState)
  
  return (
    <WeatherContext.Provider value={{ ...state, dispatch }}>
      {children}
    </WeatherContext.Provider>
  )
}

export const useWeather = () => useContext(WeatherContext)
  1. 天气查询组件
// src/components/WeatherSearch.jsx
import { useState } from 'react'
import { useWeather } from '../context/WeatherContext'
import axios from 'axios'

const WeatherSearch = () => {
  const [city, setCity] = useState('')
  const { dispatch } = useWeather()

  const handleSearch = async () => {
    try {
      dispatch({ type: 'SET_LOADING', payload: true })
      
      const response = await axios.get(
        `https://api.openweathermap.org/data/2.5/weather?q=${city}&units=metric&appid=${import.meta.env.VITE_API_KEY}`
      )
      
      dispatch({
        type: 'ADD_HISTORY',
        payload: {
          city: response.data.name,
          time: new Date().toLocaleString(),
          temp: response.data.main.temp
        }
      })
    } catch (error) {
      dispatch({ type: 'SET_ERROR', payload: error.message })
    } finally {
      dispatch({ type: 'SET_LOADING', payload: false })
    }
  }

  return (
    <div className="search-container">
      <input
        type="text"
        value={city}
        onChange={(e) => setCity(e.target.value)}
        placeholder="Enter city name"
      />
      <button onClick={handleSearch} disabled={!city.trim()}>
        Search
      </button>
    </div>
  )
}
  1. 温度单位切换
// src/components/UnitToggle.jsx
import { useWeather } from '../context/WeatherContext'

const UnitToggle = () => {
  const { unit, dispatch } = useWeather()

  return (
    <div className="unit-toggle">
      <button
        onClick={() => dispatch({ type: 'SET_UNIT', payload: 'metric' })}
        className={unit === 'metric' ? 'active' : ''}
      ></button>
      <button
        onClick={() => dispatch({ type: 'SET_UNIT', payload: 'imperial' })}
        className={unit === 'imperial' ? 'active' : ''}
      ></button>
    </div>
  )
}

性能优化

// 使用React.memo优化组件渲染
const MemoizedComponent = React.memo(({ data }) => {
  /* render logic */
})

// 使用useCallback缓存回调函数
const memoizedCallback = useCallback(() => {
  doSomething(a, b)
}, [a, b])
错误边界处理
jsx
 
class ErrorBoundary extends Component {
  state = { hasError: false }

  static getDerivedStateFromError(error) {
    return { hasError: true }
  }

  componentDidCatch(error, info) {
    logErrorToService(error, info)
  }

  render() {
    return this.state.hasError ? <FallbackUI /> : this.props.children
  }
}

项目扩展方向

添加Redux Toolkit进行复杂状态管理
集成TypeScript类型系统
实现PWA离线功能
添加Jest + React Testing Library测试
使用Chart.js实现天气趋势可视化
部署指南

创建生产构建

npm run build

部署到Vercel

npm install -g vercel
vercel deploy

总结

通过本项目的实践,我们系统性地掌握了:

React函数组件与Hooks的核心用法
上下文状态管理的最佳实践
现代前端工程化配置
第三方API集成方法
性能优化关键策略

如果你有什么疑问,欢迎你私信与我交流沟通

你可能感兴趣的:(前端学习,前端框架,react.js,前端)