Импортировать обратный вызов из класса в другой в typescript

#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);