【问题标题】:Search functionality is not working for the frontend搜索功能不适用于前端
【发布时间】:2018-10-20 21:44:02
【问题描述】:

我正在使用邮递员从后端获取数据。但是当我使用同样的前端时,它不起作用。我收到类似的错误 1.TypeError:无法读取null的属性'map' 2.Unhandled Rejection (TypeError): Cannot read property 'map' of null.

我认为,我收到此错误是因为我在搜索时无法呈现卡片。后端数据以数组的形式出现。

const styles = theme => ({
  appBar: {
    position: 'relative',
  },
  icon: {
    marginRight: theme.spacing.unit * 2,
  },
  layout: {
    width: 'auto',
    marginLeft: theme.spacing.unit * 3,
    marginRight: theme.spacing.unit * 3,
    [theme.breakpoints.up(1100 + theme.spacing.unit * 3 * 2)]: {
      width: 1100,
      marginLeft: 'auto',
      marginRight: 'auto',
    },
  },
  cardGrid: {
    padding: `${theme.spacing.unit * 8}px 0`,
  },
  card: {
    height: '100%',
    display: 'flex',
    flexDirection: 'column',
  },
  cardContent: {
    flexGrow: 1,
  },
});

class Products extends Component {


  constructor(props) {
    super(props);

    this.state = {
      products: [],
      searchString: ''
    };
    this.onSearchInputChange = this.onSearchInputChange.bind(this);
    this.getProducts = this.getProducts.bind(this);
  }

  componentDidMount() {
    this.getProducts();
  }



  // delete = id => {
  //   axios.post('http://localhost:9022/products/delete/' + id)
  //     .then(res => {
  //       let updatedProducts = [...this.state.products].filter(i => i.id !== id);
  //       this.setState({ products: updatedProducts });
  //     });
  // }

  delete = id => {
    axios.post('http://localhost:9022/products/delete/' + id)
      .then(res => {

        this.setState((prevState, prevProps) => {
          let updatedProducts = [...prevState.products].filter(i => i.id !== id);
          return ({
            products: updatedProducts
          });
        });
      });
  }

  getProducts() {
    axios.get('http://localhost:9022/products/getAll')
      .then(res => {
        this.setState({ products: res.data }, () => {
          console.log(this.state.products);
        });
      });
  }

  onSearchInputChange = (event) => {
    let newSearchString = '';
    if (event.target.value) {
      newSearchString = event.target.value;
    }
    axios.get('http://localhost:9022/products/getproducts' + newSearchString)
      .then(res => {
        this.setState({ products: res.data });
        console.log(this.state.products);
      });
    this.getProducts();
  }

  // onSearchInputChange(event) {
  //   let newSearchString = '';
  //   if (event.target.value) {
  //     newSearchString = event.target.value;
  //   }

  //   // call getProducts once React has finished updating the state using the callback (second argument)
  //   this.setState({ searchString: newSearchString }, () => {
  //     this.getProducts();
  //   });
  // }

  render() {
    const { classes } = this.props;
    return (
      <React.Fragment>
        <TextField style={{ padding: 24 }}
          id="searchInput"
          placeholder="Search for products"
          margin="normal"
          onChange={this.onSearchInputChange} />
        <CssBaseline />
        <main>
          <div className={classNames(classes.layout, classes.cardGrid)}>
            <Grid container spacing={40}>
              {this.state.products.map(currentProduct => (
                <Grid item key={currentProduct.id} sm={6} md={4} lg={3}>
                  <Card className={classes.card}>

                    <CardContent className={classes.cardContent}>
                      <Typography gutterBottom variant="h5" component="h2">
                        {currentProduct.title}
                      </Typography>
                      <Typography>
                        {currentProduct.price}
                      </Typography>
                    </CardContent>
                    <CardActions>

                      <Button size="small" color="primary" component={Link} to={"/products/" + currentProduct.id}>
                        Edit
                    </Button>
                      <Button size="small" color="primary" onClick={() => this.delete(currentProduct.id)}>
                        Delete
                    </Button>
                    </CardActions>
                  </Card>
                </Grid>
              ))}
            </Grid>
          </div>
        </main>
      </React.Fragment>
    )
  }
}

Products.propTypes = {
  classes: PropTypes.object.isRequired,
};

export default withStyles(styles)(Products);

【问题讨论】:

  • 对于初学者来说,这是getproducts' + newSearchString,而您希望查询以/ 分隔。检查您的请求和响应在网络选项卡中的内容,然后从那里继续。
  • 知道了。小错误。但是搜索后,当我删除搜索字符串时,它给出了同样的错误。
  • @Suman 特定于后端如何响应特定请求。你是唯一可以调试它们的人。你得到这个错误意味着后端用其他东西而不是数组来响应。
  • 可能是在某些情况下this.state.products 设置为null?尝试在调用map()-> {this.state.products &amp;&amp; this.state.products.map(…之前添加验证

标签: javascript reactjs


【解决方案1】:

已经观察到,您添加了错误的网址getproducts,网址中缺少斜杠。请在下面找到详细信息:

如果 search-string 是 r,那么您使用的是 getproducts 的 URL:http://localhost:9022/products/getproductsr

错了,应该是http://localhost:9022/products/getproducts/r

因此您必须更改检索产品的代码,如下所示:

axios.get('http://localhost:9022/products/getproducts/' + newSearchString)
.then(res => {
    this.setState({ products: res.data });
    console.log(this.state.products);
});

此外,最好为 this.state.products 提供 undefined/null 检查,然后渲染组件,因为如果提供了错误的 URL 并且由于 axios 请求是异步的而未定义,则 products 可能为 null。因此,通过在现有渲染代码中添加“this.state.products &&”将有助于避免此类问题。我已经更新了你的渲染函数,请在下面找到它:

render() {
    const { classes } = this.props;
    return (
      <React.Fragment>
        <TextField style={{ padding: 24 }}
          id="searchInput"
          placeholder="Search for products"
          margin="normal"
          onChange={this.onSearchInputChange} />
        <CssBaseline />
        <main>
          <div className={classNames(classes.layout, classes.cardGrid)}>
            <Grid container spacing={40}>
              {this.state.products && this.state.products.map(currentProduct => (
                <Grid item key={currentProduct.id} sm={6} md={4} lg={3}>
                  <Card className={classes.card}>

                    <CardContent className={classes.cardContent}>
                      <Typography gutterBottom variant="h5" component="h2">
                        {currentProduct.title}
                      </Typography>
                      <Typography>
                        {currentProduct.price}
                      </Typography>
                    </CardContent>
                    <CardActions>

                      <Button size="small" color="primary" component={Link} to={"/products/" + currentProduct.id}>
                        Edit
                    </Button>
                      <Button size="small" color="primary" onClick={() => this.delete(currentProduct.id)}>
                        Delete
                    </Button>
                    </CardActions>
                  </Card>
                </Grid>
              ))}
            </Grid>
          </div>
        </main>
      </React.Fragment>
    )
}

希望它会有所帮助..

【讨论】:

    【解决方案2】:

    你可以试试这个:

    您只是错过了 api 端点中的斜线,如下所示:使用此

    axios.get('http://localhost:9022/products/getproducts/' + newSearchString)
    

    而不是:

    axios.get('http://localhost:9022/products/getproducts' + newSearchString)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多