Немного застрял на этом. У меня есть родительский компонент Main, который переходит в компонент поиска, который затем переходит в компонент Select. Поиск запрашивает город, а затем обращается к API и возвращает 5 результатов поиска, и я отправляю их в компонент выбора, где сопоставляю результаты с формой выбора. Как только пользователь выбирает город и отправляет его, мне нужно, чтобы выбор был сохранен где-то в основном файле, чтобы я мог использовать его для других детей. Любая помощь приветствуется, я все еще разбираюсь в React.
Я попробовал сделать компонент Select прямым дочерним элементом основного, но мне это не понравилось. Я пытался отправить «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 handleChangeEvent = (event) => {
setSearchTerm(event.target.value);
}
const handleSubmit = (event) => {
console.info('The form submitted with input: ' + searchTerm);
setCel(() => (searchTerm - 32) / 1.8);
event.preventDefault(); // Prevent default form submission behavior
console.info(searchTerm);
fetch(`${url}?q=${searchTerm}&limit=5&appid=${Weather_API_key}&units=metric`)
.then(response => response.json())
.then(data => {
console.info(data);
setCityArray(data);
console.info('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 = {handleChangeEvent} 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 handleChangeEvent = (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.info('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 = {handleChangeEvent}
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. Большая разница в том, что при создании контекста его можно обернуть вокруг компонента или компонентов, и все эти компоненты будут иметь доступ к состоянию без необходимости передавать реквизиты вверх или вниз. Напишу небольшой пример, как это будет выглядеть:
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).
Я получаю много ошибок при попытке использовать это.
Я получаю подобные ошибки, как только помещаю новый код в свой основной раздел.
Uncaught ReferenceError: экспорт не определен
Uncaught TypeError: невозможно прочитать свойства неопределенного типа (чтение «useState»)
Код не предназначен для копирования и вставки, он просто иллюстрирует, как он будет выглядеть в вашем коде. В опубликованном мною документе по ссылке есть рабочий пример, который вы можете использовать.
Да, поставщик, вокруг которого вы обертываете свои компоненты, может использоваться внутри всех компонентов, вокруг которых он заключен, а также его дочерних компонентов.
Если вы хотите, вы можете создать воспроизводимый пример со своим кодом внутри песочницы или чего-то еще, и я могу показать, как использовать контекст, и объяснить это.
Было бы здорово, постараюсь как можно скорее что-нибудь собрать
Эта ссылка должна работать, все находится в папке «раздел A», и я включил корневой HTML-файл codeandbox.io/p/live/8d22195b-d51b-447a-aafa-2eb53d89a662
Да, дай мне немного времени
Я ценю это, большое спасибо
Я обновил песочницу кода. Я не уверен, как это проверить, потому что все это находится в отдельной папке, которая не используется. Но я уверен, что именно так и должно работать. Если это не работает, я добавлю минимальный пример в папку «src», чтобы показать вам. Надеюсь, это поможет!
Эй, я думаю, что это начинает работать, но как только я помещаю строку импорта вверху, у меня появляется ошибка
Uncaught ReferenceError: требование не определено
Вы импортируете его через require? Я думаю, это не сработает, вам придется использовать import {...} from "react";
И когда я добавляю его в компонент поиска, я получаю ту же ошибку плюс
Uncaught ReferenceError: createContext не определен
я не уверен, что именно требуется, но я только что скопировал тег импорта, который у вас есть в коде песочницы, и, похоже, он ему не нравится
Давайте продолжим обсуждение в чате.
Будет ли это работать и для доступа к моему выбранному компоненту? На данный момент структура такая: Главное – Поиск – Выбрать. Select является дочерним элементом Search. Вы объявляете CityContext вне основной функции?