无法在反应中的组件之间传递数据
Unable to pass data between components in react
我正在尝试创建一个天气应用程序来练习 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 并更新温度。
- 我想在温度变化时传递变化背景。
<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
已经给你解答了
这是一个让搜索工作的分叉示例:
我正在尝试创建一个天气应用程序来练习 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 并更新温度。
- 我想在温度变化时传递变化背景。
<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
已经给你解答了
这是一个让搜索工作的分叉示例: