You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js跨组件共享数据与状态实现方法咨询

解决方案

你遇到的是React兄弟组件共享状态的典型场景,不需要引入额外复杂库,用状态提升的原生React方案就能实现:把两个组件都需要依赖的「当前查询城市」状态,放到Search和CardList共同的父组件中管理,再通过props分别向两个子组件传递状态、更新状态的回调即可。


具体实现步骤

1. 改造共同父组件

假设你两个组件都挂载在页面级父组件(比如Home.tsx/WeatherApp.tsx)中,在这里定义共享的城市状态,以及更新城市的方法:

import { useState } from 'react';
import { Search } from './Search/Search';
import { CardList } from './CardList/CardList';

export const WeatherApp = () => {
  // 共享状态:当前要查询的城市,默认值设为London兼容原有逻辑
  const [currentCity, setCurrentCity] = useState('London');

  return (
    <div>
      {/* 把更新城市的回调传给Search组件 */}
      <Search onSubmitCity={setCurrentCity} />
      {/* 把当前城市传给CardList组件用来拉取数据 */}
      <CardList city={currentCity} />
    </div>
  )
}

2. 改造Search组件

输入框的临时输入值依然存在组件内部即可,接收父组件传入的提交回调,用户点击搜索按钮时触发回调,把输入的城市名传回父组件:

import { SearchProps } from "./Search.props";
import styles from "./Search.module.css";
import cn from 'classnames';
import { Input } from "../Input/Input";
import { Button } from "../Button/Button";
import { useState } from "react";
import GlassIcon from './glass.svg';
import { cookies } from "../../libs/setCookie";

// 扩展props类型,新增提交城市的回调定义
interface SearchExtendedProps extends SearchProps {
  onSubmitCity: (city: string) => void
}

export const Search = ({ className, onSubmitCity, ...props }: SearchExtendedProps): JSX.Element => {
  const [inputValue, setInputValue] = useState<string>("");

  const handleOnClick = () => {
    // 输入为空时不触发查询
    if (!inputValue.trim()) return;
    // 调用父组件传入的回调,把输入的城市传回父组件
    onSubmitCity(inputValue.trim());
    setInputValue(""); // 可选:提交后清空输入框
  }

  const handleOnChange = (event) => {
    setInputValue(event.target.value);
  }

  return (
    <div className={cn(className, styles.search)} {...props} >
      <Button
        appearance="ghost"
        className={styles.button}
        onClick={handleOnClick}
      >
        <GlassIcon />
      </Button>
      <Input
        className={styles.input}
        placeholder="Search location here"
        value={inputValue}
        onChange={handleOnChange}
        // 可选:支持回车键直接触发搜索
        onKeyDown={(e) => e.key === 'Enter' && handleOnClick()}
      />
    </div>
  )
};

如果你需要保留之前的搜索城市列表citiesList,把这个状态也提升到父组件管理即可,逻辑和当前城市状态一致。

3. 改造CardList组件

接收父组件传入的城市参数,替换原来硬编码的London,同时把城市加到useEffect的依赖数组里,城市变化时自动重新拉取对应城市的天气数据:

import { CardListProps } from "./CardList.props";
import styles from "./CardList.module.css";
import React, { useState, useEffect } from 'react';
import { Card } from "../Card/Card";
import { API_KEY } from './settings';

// 扩展props类型,接收传入的城市参数
interface CardListExtendedProps extends CardListProps {
  city: string
}

export const CardList = ({ children, city, ...props }: CardListExtendedProps): JSX.Element => {
  const [data, setData] = useState(null);

  useEffect(() => {
    // 用传入的city替换硬编码的London,加encodeURIComponent处理特殊字符
    fetch(`https://api.openweathermap.org/data/2.5/weather?q=${encodeURIComponent(city)}&appid=${API_KEY}&units=metric`)
    .then(res => res.json())
    .then(setData)
    .catch(err => console.error('获取天气数据失败:', err));
  }, [city]); // 把city加入依赖,城市变化就自动重新发请求

  if (!data) return null;
  const { name, weather, main, wind, clouds } = data;
  const { description, icon } = weather[0];
  const { temp, humidity, feels_like, pressure } = main;
  const { speed } = wind;
  const { all } = clouds;

  return (
    <div
      className={styles.CardList}
      {...props}
    >
      <Card name="Wind Speed" info={parseFloat(speed.toFixed(2))+'km/h'}></Card>
      <Card name="Clouds" info={all + '%'}></Card>
      <Card name="Pressure" info={pressure + ' hpa'}></Card>
      <Card name="Humidity" info={humidity + '%'}></Card>
    </div>  
  )
};

后续扩展说明

如果后续组件嵌套层级变深,靠props一层层传状态太繁琐,可以再按需升级方案:

  • 跨层级共享少量全局状态用React内置的Context API即可
  • 轻量全局状态管理可以选Zustand、Jotai这类库,代码侵入性很低
  • 涉及大量接口缓存、异步状态管理可以考虑React Query、RTK Query这类方案

当前需求用状态提升完全足够,代码改动最小也最好维护。


内容的提问来源于stack exchange,提问作者user17880509

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 02:18:03