使搜索框正常运行

时间:2018-12-19 20:18:11

标签: reactjs search google-maps-react codesandbox

我正在React中做一个地图项目,并使用google-maps-react api。我可以在搜索框中输入字符,但不能过滤列表或标记。我该怎么做?


这是我的App.js的代码。我有updateQuery,它应使用搜索框中键入的内容进行更新。 filterItems应该用于过滤所有位置。应该用过滤的标记替换addRealMarkers:

var foursquare = require("react-foursquare")({
  clientID: "BTMAGTC2Y5G1IXAKA4VN4QN55R2DSN1105Y1XGHB0WZ5THHR",
  clientSecret: "4HOKQ0ON1V1XEHKSUSEABQMNRFZGCGPIKIUIE5JMUMWVRG5W",
  url: "https://api.foursquare.com/v2/venues/search?"
});

var params = {
  ll: "31.462170,-97.195732",
  query: "Hewitt"
};

class App extends Component {
  /* Basic state object that must be kept at the highest "parent" level per 
Doug Brown's training video */
  constructor(props) {
    super(props);
    this.state = {
      lat: 31.46217,
      lon: -97.195732,
      zoom: 13,
      items: [],
      filtered: null,
      open: false,
      selectedId: null,
      activeMarker: null
    };
  }
  realMarkers = [];
  componentDidMount() {
    foursquare.venues.getVenues(params).then(res => {
      this.setState({ items: res.response.venues });
    });
    fetch("react-foursquare")
      .then(response => response.json())
      .then(response => {
        const items = json.response.items;
        this.setState({
          items,
          filtered: this.filterItems(items, "")
        });
      })
      .catch(error => {
        alert("Foursquare data could not be retrieved");
      });
  }

  //Fetches the locations requested for this map.
  /*fetchPlaces(mapProps, map) {
    const { google } = mapProps;
    const service = new google.maps.places.PlacesService(map);
  }

  //fetch Foursquare API data and use Axios to catch errors, instructed by 
  Yahya Elharony.
  // Source: https://github.com/foursquare/react-foursquare
  getPlaces = () => {
    const endPoint = "https://api.foursquare.com/v2/venues/explore?";
    const params = {
      client_id: "BTMAGTC2Y5G1IXAKA4VN4QN55R2DSN1105Y1XGHB0WZ5THHR",
      client_secret: "4HOKQ0ON1V1XEHKSUSEABQMNRFZGCGPIKIUIE5JMUMWVRG5W",
      near: "Hewitt",
      query: "query",
      v: 20181117
    };
    // axios site: https://www.npmjs.com/package/axios
    axios
      .get(endPoint + new URLSearchParams(params))
      .then(response => {
        this.setState(
          {
            venues: response.data.response.groups[0].items
          },
          this.fetchPlaces()
        );
      })
      .catch(error => {
        console.log("ERROR! " + error);
      });
  };*/

  // Creating the replacement markers that goes with the list. Based on my 
  1:1 training from Doug Brown
  addRealMarker = marker => {
    let checkList = this.realMarkers.filter(
      m => m.marker.id === marker.marker.id
    );
    if (!checkList.length) this.realMarkers.push(marker);
  };

  updateQuery = query => {
    this.setState({
      selectedIndex: null,
      filtered: this.filterItems(this.state.items, query)
    });
  };

  filterItems = (items, query) => {
    return items.filter(item =>
      item.name.toLowerCase().includes(query.toLowerCase())
    );
  };

  clickListItem = id => {
    const marker = this.realMarkers.filter(
      marker => marker.marker.id === id
    )[0];
    this.setState({
      selectedId: id,
      activeMarker: marker
    });
  };

  /*Google Maps React Component courtesy of 
  https://www.npmjs.com/package/google-maps-react*/
  render() {
    const style = {
      width: "100%",
      height: "100%"
    };

    return (
      <div className="App">
        <HewittMap
          lat={this.state.lat}
          lng={this.state.lng}
          zoom={this.state.zoom}
          style={style}
          items={this.state.items}
          addRealMarker={this.addRealMarker}
          activeMarker={this.state.activeMarker}
          clickListItem={this.clickListItem}
        />
        <Sidebar
          items={this.state.items}
          clickListItem={this.clickListItem}
          filterItems={this.updateQuery}
        />
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));

export default App;

这是补充工具栏代码。添加了另一个应该调用道具的updateQuery函数,然后您会在InputBase组件中看到更多代码:

class Sidebar extends Component {
  state = {
    mobileOpen: false,
    query: ""
  };

  handleDrawerOpen = () => {
    this.setState({ open: true });
  };

  handleDrawerClose = () => {
    this.setState({ open: false });
  };

  updateQuery = newQuery => {
    // Save the new query string in state and pass the string up the call 
    tree
    this.setState({ query: newQuery });
    this.props.filterItems(newQuery);
  };

  render() {
    const { classes, theme } = this.props;
    const { open } = this.state;
    const items = this.props.items;

    return (
      <div className={classes.root}>
        <CssBaseline />
        <AppBar
          position="fixed"
          className={classNames(classes.appBar, {
            [classes.appBarShift]: open
          })}
    >
      <Toolbar disableGutters={!open}>
        <IconButton
          color="inherit"
          aria-label="Open drawer"
          onClick={this.handleDrawerOpen}
          className={classNames(classes.menuButton, open && classes.hide)}
        >
          <MenuIcon />
        </IconButton>
        <Typography variant="h6" color="inherit" noWrap>
          City of Hewitt
        </Typography>
        <div className={classes.search}>
          <div className={classes.searchIcon}>
            <SearchIcon places={this.state.places} />
          </div>
          <InputBase
            classes={{
              root: classes.inputRoot,
              input: classes.inputInput
            }}
            placeholder="Search…"
            name="filter"
            type="text"
            value={this.state.query}
            onChange={e => {
              this.updateQuery(e.target.value);
            }}
          />
        </div>
      </Toolbar>
    </AppBar>
    <Drawer
      className={classes.drawer}
      variant="persistent"
      anchor="left"
      open={open}
      classes={{
        paper: classes.drawerPaper
      }}
    >
      <div className={classes.drawerHeader}>
        <IconButton onClick={this.handleDrawerClose}>
          {theme.direction === "ltr" ? (
            <ChevronLeftIcon />
          ) : (
            <ChevronRightIcon />
          )}
        </IconButton>
      </div>
      <Divider />
      <List>
        {this.props.items &&
          this.props.items.map((item, index) => {
            return (
              <ListItem key={item.id}>
                <button
                  key={index}
                  onClick={e => this.props.clickListItem(item.id)}
                >
                  <ListItemText primary={item.name}> </ListItemText>
                </button>
              </ListItem>
            );
          })}
      </List>

      <Divider />
    </Drawer>
    <main
      className={classNames(classes.content, {
        [classes.contentShift]: open
      })}
    >
      <div className={classes.drawerHeader} />
    </main>
  </div>
);


 }
}

Sidebar.propTypes = {
  classes: PropTypes.object.isRequired,
  // Injected by the documentation to work in an iframe.
  // You won't need it on your project.
  container: PropTypes.object,
  theme: PropTypes.object.isRequired
};

export default withStyles(styles, { withTheme: true })(Sidebar); 

您可以单击我的CodeSandbox亲自查看。

1 个答案:

答案 0 :(得分:0)

您正在过滤数据并将其分配给filtered,但是您使用items来驱动地图,而不是filtered。它将需要更多的重构,但是如果您这样做,该怎么办?

  updateQuery = query => {
    this.setState({
      selectedIndex: null,
      //filtered: this.filterItems(this.state.items, query) // -
      items: this.filterItems(this.state.items, query) // +
    });
  };

您可能想要一个指示符,例如isFiltered,即当搜索栏上有一个值时,它就是true。如果true,请使用过滤后的数据,否则,请使用原始的items