#reactjs #typescript
#reactjs #typescript
Вопрос:
Я использую typescript 3.
У меня есть этот компонент map :
import * as React from 'react';
import GoogleMapReact from 'google-map-react';
import { any } from 'prop-types';
import {Coords} from 'google-map-react';
export interface HelloProps { center: Coords ; zoom: number ; }
const AnyReactComponent = ( {text} : { lat: any,text:any,lng:any}) => <div>{text}</div>;
export class SimpleMap extends React.Component <HelloProps, {}> {
defaultProps = {
center: {
lat: 59.95,
lng: 30.33
},
zoom: 11
};
myCallbackMap = (dataFromChild:number) => {
this.defaultProps.zoom = dataFromChild;
}
render() {
return (
// Important! Always set the container height explicitly
<div style={{ height: '100vh', width: '100%' }}>
<GoogleMapReact
bootstrapURLKeys={{ key: 'AIzaSyDs5u7u1Almh8-Jch3cHzuWB-egVPTZajs' }}
defaultCenter={this.props.center}
defaultZoom={this.props.zoom}
>
<AnyReactComponent
lat={59.955413}
lng={30.337844}
text="My Marker"
/>
</GoogleMapReact>
</div>
);
}
}
export default SimpleMap;
И я хочу использовать :
myCallbackMap = (dataFromChild:number) => {
this.defaultProps.zoom = dataFromChild;
}
В моей строке поиска, поэтому, когда кто-то ищет его, измените карту.
Вот мой файл поиска (прокрутите вниз, чтобы увидеть вызов) :
import * as React from 'react';
import axios from 'axios'
import Suggestions from './Suggestions'
import myCallbackMap from './Map'
const API_KEY:string = "process.env"
const API_URL:string = 'http://127.0.0.1:9001/v1/test'
export class Search extends React.Component{
state = {
query: '' as string,
results : [] as any[]
}
search = {
value: '' as string,
}
getInfo = () => {
axios.post(`${API_URL}/${this.state.query}/`)
.then(({ data }) => {
this.setState({
results: data.data
})
})
}
handleInputChange = () => {
this.setState({
query: this.search.value
}, () => {
if (this.state.query amp;amp; this.state.query.length > 1) {
if (this.state.query.length % 2 === 0) {
this.getInfo()
}
} else if (!this.state.query) {
}
})
}
myCallbackSearch = (dataFromChild:string) => {
this.search.value = dataFromChild;
// here where i want ot use the map call back
myCallbackMap(111);
}
render() {
return (
<form>
<input
placeholder="Search for..."
ref={input => this.search = input}
onChange={this.handleInputChange}
/>
<Suggestions results={this.state.results} callbackFromParentSearch={this.myCallbackSearch}/>
</form>
)
}
}
export default Search
Как правильно использовать и импортировать обратный вызов map и использовать его в поисковом компоненте? Основная цель состоит в том, чтобы, когда кто-то вводит в строке поиска, это динамически изменяло отображение. но сейчас я работаю над простым прототипом.
С уважением
Ответ №1:
Вы не можете импортировать его, потому что это была бы статическая функция, когда вам нужна функция экземпляра.
Вы должны передать обратный вызов в качестве поддержки компонента поиска.
Сам обратный вызов на самом деле выглядит как обработчик событий, роль которого заключается в изменении реквизитов по умолчанию (которые должны быть объявлены статическими) карты Google в другом компоненте. Итак, я предполагаю, что вы на самом деле не хотите изменять реквизиты карты по умолчанию, а скорее присвоите ей новое значение масштабирования через props.
Вы можете либо:
Внедрите обработчик в общем предке как для компонента search, так и для компонента map, сделайте масштабирование состоянием этого общего предка, обновите это состояние в обратном вызове и распространите через props обратный вызов вплоть до компонента search, а значение масштабирования вплоть до компонента map.
Или:
Поместите это состояние в хранилище redux, которое позволит вам пропустить цепочку реквизитов и напрямую зарегистрировать map для прослушивания изменения масштаба в хранилище, а также передать action creator компоненту search, чтобы он мог уведомлять хранилище об изменении поиска.
Версия общего предка:
import * as React from 'react';
import axios from 'axios';
import Suggestions from './Suggestions'
const API_KEY:string = "process.env"
const API_URL:string = 'http://127.0.0.1:9001/v1/test'
export class Search extends React.Component{
state = {
query: '' as string,
results : [] as any[]
}
search = {
value: '' as string,
}
getInfo = () => {
axios.post(`${API_URL}/${this.state.query}/`)
.then(({ data }) => {
this.setState({
results: data.data
})
})
}
handleInputChange = () => {
this.setState({
query: this.search.value
}, () => {
if (this.state.query amp;amp; this.state.query.length > 1) {
if (this.state.query.length % 2 === 0) {
this.getInfo()
}
} else if (!this.state.query) {
}
})
}
myCallbackSearch = (dataFromChild:string) => {
this.search.value = dataFromChild;
// here where i want ot use the map call back
myCallbackMap(111);
}
render() {
const { callbackFromParentSearch } = this.props;
return (
<form>
<input
placeholder="Search for..."
ref={input => this.search = input}
onChange={this.handleInputChange}
/>
<Suggestions results={this.state.results} callbackFromParentSearch={callbackFromParentSearch}/>
</form>
)
}
}
export default Search;
Обратите внимание, что компонентам не обязательно иметь одного и того же точного родителя, приведенный ниже пример. Это все равно будет работать, если вы передаете реквизиты от родителя к потомку, пока не дойдете до целевых объектов Search и SimpleMap.
export default class CommonAncestor extends Component {
state: {
zoom: 3 as number,
}
handleCallbackFromParentSearch = (dataFromChild:number) => {
this.setState(() => ({ zoom: dataFromChild }));
}
render() {
const { zoom } = this.state;
return (
<React.Fragment>
<Search callbackFromParentSearch={this.handleCallbackFromParentSearch} />
<SimpleMap zoom={zoom} />
</React.Fragment>
);
}
}
Версия Redux:
Компонент поиска, подключенный к действию changeZoom
import * as React from 'react';
import axios from 'axios';
import { connect } from 'react-redux';
import Suggestions from './Suggestions';
import { actionCreators as zoomAC } from 'src/redux/zoom';
const API_KEY:string = "process.env"
const API_URL:string = 'http://127.0.0.1:9001/v1/test'
class Search extends React.Component{
state = {
query: '' as string,
results : [] as any[]
}
search = {
value: '' as string,
}
getInfo = () => {
axios.post(`${API_URL}/${this.state.query}/`)
.then(({ data }) => {
this.setState({
results: data.data
})
})
}
handleInputChange = () => {
this.setState({
query: this.search.value
}, () => {
if (this.state.query amp;amp; this.state.query.length > 1) {
if (this.state.query.length % 2 === 0) {
this.getInfo()
}
} else if (!this.state.query) {
}
})
}
myCallbackSearch = (dataFromChild:string) => {
this.search.value = dataFromChild;
// here where i want ot use the map call back
myCallbackMap(111);
}
render() {
const { changeZoom} = this.props;
return (
<form>
<input
placeholder="Search for..."
ref={input => this.search = input}
onChange={this.handleInputChange}
/>
<Suggestions results={this.state.results} callbackFromParentSearch={changeZoom}/>
</form>
)
}
}
export default connect(
null,
dispatch => ({
changeZoom: value => dispatch(zoomAC.changeZoom(value))
})
)(Search);
Компонент SimpleMap, подключенный к хранилищу масштабирования:
import * as React from 'react';
import GoogleMapReact from 'google-map-react';
import { connect } from 'react-redux';
import { any } from 'prop-types';
import {Coords} from 'google-map-react';
export interface HelloProps { center: Coords ; zoom: number ; }
const AnyReactComponent = ( {text} : { lat: any,text:any,lng:any}) => <div>{text}</div>;
export class SimpleMap extends React.Component <HelloProps, {}> {
defaultProps = {
center: {
lat: 59.95,
lng: 30.33
},
zoom: 11
};
render() {
return (
// Important! Always set the container height explicitly
<div style={{ height: '100vh', width: '100%' }}>
<GoogleMapReact
bootstrapURLKeys={{ key: 'AIzaSyDs5u7u1Almh8-Jch3cHzuWB-egVPTZajs' }}
defaultCenter={this.props.center}
defaultZoom={this.props.zoom}
>
<AnyReactComponent
lat={59.955413}
lng={30.337844}
text="My Marker"
/>
</GoogleMapReact>
</div>
);
}
}
export default connect(
state => ({ zoom: state.zoom })
)(SimpleMap);