首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使搜索框起作用

使搜索框起作用
EN

Stack Overflow用户
提问于 2018-12-20 04:18:11
回答 1查看 70关注 0票数 -1

我正在用React做一个地图项目,使用的是google-maps-react api。我可以在搜索框中键入字符,但它不会过滤我的列表或标记。我怎么才能做到这一点呢?

这是我的App.js的代码。我有updateQuery,它应该会随着在搜索框中键入的任何内容而更新。filterItems应该会过滤所有的位置。addRealMarkers应该替换为过滤后的标记:

代码语言:javascript
复制
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组件中看到更多代码:

代码语言:javascript
复制
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中单击以亲自查看。

EN

回答 1

Stack Overflow用户

发布于 2018-12-20 06:01:41

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

代码语言:javascript
复制
  updateQuery = query => {
    this.setState({
      selectedIndex: null,
      //filtered: this.filterItems(this.state.items, query) // -
      items: this.filterItems(this.state.items, query) // +
    });
  };

当搜索栏中有一个值时,您可能需要一个指示器,比如isFiltered,它是true。如果为true,则使用过滤后的数据,否则,使用原始items

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53858584

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档