有点卡在这个上了。我有一个主要父组件,它转到搜索组件,然后转到选择组件。搜索请求一个城市,然后转到 API 并返回 5 个搜索结果,我将它们发送到选择组件,在其中将结果映射到选择表单中。一旦用户选择城市并提交,我需要将选择存储在主目录中的某个位置,以便我可以在其他孩子身上使用它。感谢任何帮助,仍然可以掌握 React。
我尝试过让 Select 组件成为 main 的直接子组件,但它不喜欢那样。 我尝试过将“cityObj”通过搜索发送到选择中,但没有成功,除非我做错了什么。 我虽然可能会将需要信息的“主体”组件作为“选择”的子组件,但我仍在努力。
Main.js
function Main() {
const [cityObj, setCityObj] = React.useState('');
return (
<div className="container p-5 bg-primary">
<i className='text-danger fw-bold'>Main component</i>
<h2 className='m-3'>My React Weather Application</h2>
<Search />
<hr />
<Body />
</div>
);
}
搜索.js
function Search(props) {
const [searchTerm, setSearchTerm] = React.useState('');
const [cityArray, setCityArray] = React.useState([]);
const [cel, setCel] = React.useState(null);
const [selectedCity, setSelectedCity] = React.useState(null);
const Weather_API_key = '55c5392db030dbb75249aa1ff9b8a871';
const url = 'http://api.openweathermap.org/geo/1.0/direct';
const handleChange = (event) => {
setSearchTerm(event.target.value);
}
const handleSubmit = (event) => {
console.log('The form submitted with input: ' + searchTerm);
setCel(() => (searchTerm - 32) / 1.8);
event.preventDefault(); // Prevent default form submission behavior
console.log(searchTerm);
fetch(`${url}?q=${searchTerm}&limit=5&appid=${Weather_API_key}&units=metric`)
.then(response => response.json())
.then(data => {
console.log(data);
setCityArray(data);
console.log('API data came mounted');
});
}
return (
<div className="container p-3 bg-success">
<i className='text-danger fw-bold'>Search component</i>
<form onSubmit={handleSubmit} className='my-3 row g-3'>
<label className="col-sm-4 col-form-label">
Please enter city name:
</label>
<div className="col-sm-4">
<input type="text" value={searchTerm}
onChange={handleChange} className="form-control" />
</div>
<div className="col-sm-4">
<input type="submit" value="Search" className="btn btn-primary mb-3" />
</div>
</form>
<Select cityArray={cityArray} />
</div>
);
}
选择.js
function Select(props) {
const [userInput, setUserInput] = React.useState('');
const [selectedValue, setSelectedValue] = React.useState(null);
const handleChange = (event) => {
// Get the input from the user and save it in a state variable
// event.target is the input element
setUserInput(event.target.value);
}
const handleSubmit = (event) => {
console.log('The form submitted with input: ' + userInput);
setSelectedValue(() => userInput);
event.preventDefault(); // Prevent default form submission behavior
}
return (
<div className="container p-3 bg-warning">
<i className='text-danger fw-bold'>Select component</i>
<form onSubmit={handleSubmit} className=' row g-3'>
<label className="col-sm col-form-label">
Choose your country:</label>
<select value={userInput} onChange={handleChange}
className='form-select col-md'>
{props.cityArray.map((city, index) =>
<option key={city.name + index} value={`${city.name} , ${city.country}`}>
{city.name}, {city.country}</option>
)}
</select>
<div className="col-sm col-form-label">
<input type="submit" value="Submit" className="btn btn-primary mb-3" />
</div>
</form>
{
selectedValue &&
<div> You selected {selectedValue} </div>
}
</div>
);
}
解决方案是使用
React Context
。什么是反应上下文?它是 React 中的一种状态,其功能类似于 useState
钩子。最大的区别是,在创建上下文时,它可以包裹在一个或多个组件周围,并且所有这些组件都可以访问状态,而不需要向上或向下传递 props。我会写一个简短的例子,它会是什么样子:
Main.js
:
import { createContext, useState } from 'react';
const CityContext = createContext();
export function Main() {
const [cityObj, setCityObj] = useState();
return (
<CityContext.Provider value={{ cityObj, setCityObj }}>
<Search />
<Body />
</CityContext.Provider>
);
}
在上面的代码中,我们使用
createContext
钩子创建了一个上下文,并将其包裹在我们的 Search
和 Body
组件周围。现在,上下文提供程序内的所有组件都可以访问 cityObj
和 setCityObj
。我们如何使用和改变上下文?
Search.js
let { cityObj, setCityObj } = useContext(CityContext);
const changeCityState = () => {
setCityObj({exampleObj: "example"});
}
return (
<div>
{cityObj}
</div>
);
在上面的代码中,我们使用
useContext
钩子并将 CityContext 作为参数传递以访问上下文提供者的 value
。现在我们可以像“正常”状态一样使用上下文。如果更改状态,则使用状态的每个组件都将重新渲染!我建议阅读更多内容(https://react.dev/reference/react/createContext)。