【问题标题】:Unable to pass data between components in react无法在反应中的组件之间传递数据
【发布时间】:2022-01-21 05:35:06
【问题描述】:

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

我有 3 个组件:

  • Form.jsx
  • Weather.jsx
  • WeatherDetail.jsx

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;

不适合我的事情:

  • 当我更改城市时,由于某种原因 setCity(value) 不会调用 API 并更新 temp。
  • 我想在温度变化时传递变化背景。

    <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>

但数据似乎没有通过。

我尝试与几个开发者朋友交谈,但无法解决问题。提前谢谢你。

【问题讨论】:

    标签: reactjs react-hooks use-effect


    【解决方案1】:

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

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

    Form - 当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 请求/weatherData 服务中捕获被拒绝的 Promise。

    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 状态可能未定义,您应该使用可选链接运算符有条件地渲染类。

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

    【讨论】:

      【解决方案2】:

      抱歉,如果我遗漏了什么......但我做了一个简单的改变,它似乎对我有用。我自己是 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已经给你答案了。

      【讨论】:

        【解决方案3】:

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

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

        【讨论】:

          猜你喜欢
          • 2016-05-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-09-28
          • 1970-01-01
          • 2020-03-11
          • 2021-06-30
          相关资源
          最近更新 更多