无法在反应中的组件之间传递数据

Unable to pass data between components in react

我正在尝试创建一个天气应用程序来练习 React,但遇到了一些问题。你可以在这里找到我的代码:Codesandbox

我有 3 个组件:

Weather.jsx

我正在使用 axios 从 openweather API 中提取数据。默认城市设置为“纽约”。将 {data, city, set city, handleClick} 作为道具传递给 Form.jsx。


    const Weather = () => {
      const [data, geWeatherData] = useState(undefined);
      const [city, setCity] = useState("New York");
      const [click, handleClick] = useState(false);
    
      useEffect(() => {
        if (!click) {
          const getWeather = async () => {
            city &&
              (await weatherData(city).then((response) => {
                geWeatherData(response.data);
                // console.log(response.data);
                console.log(response.data.main.temp);
              }));
          };
          getWeather();
          handleClick(true);
        }
      }, [click, city]);
    
      const classes = useStyles();
      return (
        <Box className={classes.component}>
          <Box className={classes.weatherContainer}>
            <Form
              data={data}
              city={city}
              setCity={setCity}
              handleClick={handleClick}
            />
          </Box>
        </Box>
      );
    };
    ```
    **Form.jsx**
    
    I'm planning to use this component to design the input but also get the city from the user.I'm also passing data to WeatherDetail component so that I can show content. Ideally, I should make this into a separate one, I decided to just club them together.
    ```
    const Form = ({ city, setCity, handleClick, data }) => {
      const classes = useStyles();
    
      const handleCityChange = (value) => {
        setCity(value);
      };
      return (
        <>
          <Box>
            <TextField
              inputProps={{ className: classes.input }}
              value={city}
              autoFocus
              className={classes.input}
              onKeyPress={(e) => {
                if (e.key === "Enter") {
                  handleClick(true);
                }
              }}
              onChange={(e) => handleCityChange(e.target.value)}
              label="Enter any City in USA"
              variant="standard"
            />
          </Box>
          <Weatherdetail data={data} />
        </>
      );
    };
    
    export default Form;

WeatherDetail.jsx

从 API 传递城市和数据以构建城市天气的视觉细节。


    const WeatherDetail = ({ data }) => {
      const classes = useStyles();
      return data ? (
        <>
          <Box className={classes.temp} component="div">
            {data.main.temp}
            <Box style={{ fontSize: "10px" }} component="span">
              Fahranheit
            </Box>
          </Box>
        </>
      ) : (
        <Box>
          <p>Lets do something</p>
        </Box>
      );
    };
    
    export default WeatherDetail;

不适合我的事情:


    <Box className={data.main.temp < 40 ?classes.componentFog : classes.component}>
          <Box className={classes.weatherContainer}>
            <Form
              data={data}
              city={city}
              setCity={setCity}
              handleClick={handleClick}
            />
          </Box>
        </Box>

但是数据好像没有通过

我尝试与一些开发朋友交谈但无法解决问题。提前谢谢你。

您只将 click 设置为 true 一次,它永远不会切换回 false,因此可以进行其他查询。

您还需要处理失败的天气请求。

表单 - 当 TextField 与您交互时,您应该重置 click 状态。

const Form = ({ city, setCity, handleClick, data }) => {
  const classes = useStyles();

  const handleCityChange = (value) => {
    handleClick(false); // <-- onChange reset the click state
    setCity(value);
  };
  
  return (
    <>
      <Box>
        <TextField
          inputProps={{ className: classes.input }}
          value={city}
          autoFocus
          className={classes.input}
          onKeyPress={(e) => {
            if (e.key === "Enter") {
              handleClick(true);
            }
          }}
          onChange={(e) => handleCityChange(e.target.value)}
          label="Enter any City in USA"
          variant="standard"
        />
      </Box>
      <Weatherdetail data={data} />
    </>
  );
};

天气 - 从 axios requests/weatherData 服务中捕获被拒绝的承诺。

useEffect(() => {
  if (!click) {
    const getWeather = async () => {
      city &&
        (await weatherData(city).then((response) => {
          geWeatherData(response.data);
          console.log(response.data.main.temp);
        }).catch(error => {
          // log/show error message/etc... 
        }));
    };
    getWeather();
    handleClick(true);
  }
}, [click, city]);

由于 data 状态可能未定义,您应该使用可选链接运算符有条件地呈现 class。

className={data?.main?.temp < 40 ? classes.componentFog : classes.component}

抱歉,如果我遗漏了什么..但我做了一个简单的改变,它似乎对我有用。我自己是 React 的新手,昨晚才开始接触它。但这里是代码:

const Weather = () => {
  const [data, geWeatherData] = useState(undefined);
  const [city, setCity] = useState("New York");
  const [click, handleClick] = useState(false); // not sure why this is used


  const updateApi = () => {
    const getWeather = async () => {
      city &&
        (await weatherData(city).then((response) => {
          geWeatherData(response.data);
          console.log(response.data.main.temp);
        }));
    };
    getWeather();
  }

  // useEffect(() => {
  //   if (!click) {
  //     const getWeather = async () => {
  //       city &&
  //         (await weatherData(city).then((response) => {
  //           geWeatherData(response.data);
  //           // console.log(response.data);
  //           console.log(response.data.main.temp);
  //         }));
  //     };
  //     getWeather();
  //     handleClick(true);
  //   }
  // }, [click, city]);

  const classes = useStyles();
  return (
    <Box className={classes.component}>
      <Box className={classes.weatherContainer}>
        <Form
          data={data}
          city={city}
          setCity={setCity}
          handleClick={updateApi} // Altered line here
        />
      </Box>
    </Box>
  );
};

export default Weather;

我想你是通过按键 (Enter) 来搜索城市的。所以我认为最好在按下 Enter 时调用一个函数 (updateApi)。

关于背景变化,我看到Drew Reese已经给你解答了

这是一个让搜索工作的分叉示例:

https://codesandbox.io/s/newweather-dec-forked-113re