React.js history.push в отдельной функции? - PullRequest
0 голосов
/ 13 сентября 2018

Можете ли вы помочь мне с функцией React.js history.push?

У меня есть значок, который можно нажать. OnClick вызывает функцию handleRemoveFavourite, которая отфильтровывает текущий элемент из localStrorage и устанавливает обновленную строку в хранилище. Это отлично работает.

После обновления хранилища программа должна перенаправить пользователя на корневую страницу / избранное. Перенаправление хорошо работает в нижнем примере. Но как это сделать в функции handleRemoveFavourites?

Это код, который я хотел бы получить

handleRemoveFavourite = () => {
    const { name } = this.props.workout;
    let savedStorage = localStorage.saved.split(",");
    let cleanedStorage = savedStorage.filter(function(e) {
      return e !== name;
    });
    localStorage.setItem("saved", cleanedStorage.toString());
    history.push("/favourites")
  };

  renderHeartIcon = () => {
    return (
      <Route
        render={({ history }) => (
          <Rating
            icon="heart"
            defaultRating={1}
            maxRating={1}
            onClick={this.handleRemoveFavourite}
          />
        )}
      />
    );
  };

Перенаправление отлично работает только с этим:

  renderHeartIcon = () => {
    return (
      <Route
        render={({ history }) => (
          <Rating
            key={1}
            icon="heart"
            defaultRating={1}
            maxRating={1}
            size="large"
            onClick={() => history.push("/favourites")}
          />
        )}
      />
    );
  };

Весь компонент выглядит так:

import React from "react";
import {
  Container,
  Grid,
  Icon,
  Label,
  Table,
  Header,
  Rating,
  Segment
} from "semantic-ui-react";
import { Link, Route } from "react-router-dom";

export default class WorkoutComponent extends React.PureComponent {
  renderChallengeRow = workouts => {
    let { reps } = this.props.workout;
    reps = reps.split(",");

    return workouts.map((item, i) => {
      return (
        <Table.Row key={item.id}>
          <Table.Cell width={9}>{item.name}</Table.Cell>
          <Table.Cell width={7}>{reps[i]}</Table.Cell>
        </Table.Row>
      );
    });
  };

  handleRemoveFavourite = () => {
    const { name } = this.props.workout;
    let savedStorage = localStorage.saved.split(",");
    let cleanedStorage = savedStorage.filter(function(e) {
      return e !== name;
    });
    localStorage.setItem("saved", cleanedStorage.toString());
    // history.push("/favourites");
  };

  renderHeartIcon = () => {
    return (
      <Route
        render={({ history }) => (
          <Rating
            key={1}
            icon="heart"
            defaultRating={1}
            maxRating={1}
            size="large"
            onClick={this.handleRemoveFavourite}
          />
        )}
      />
    );
  };

  render() {
    const { name, workouts } = this.props.workout;
    const url = `/savedworkout/${name}`;
    return (
      <Grid.Column>
        <Segment color="teal">
          <Link to={url}>
            <Header as="h2" to={url} content="The workout" textAlign="center" />
          </Link>
          <Table color="teal" inverted unstackable compact columns={2}>
            <Table.Body>{this.renderChallengeRow(workouts)}</Table.Body>
          </Table>
          <br />
          <Container textAlign="center">
            <Label attached="bottom">{this.renderHeartIcon()}</Label>
          </Container>
        </Segment>
        <Link to="/generate">
          <Icon name="angle double left" circular inverted size="large" />
        </Link>
      </Grid.Column>
    );
  }
}

Ответы [ 4 ]

0 голосов
/ 13 сентября 2018

Проблема, с которой вы сталкиваетесь, заключается в том, что вы предоставляете <Route> с историей, чтобы она распространялась при вызове функции компонента. Но вы не передаете его в функцию handleRemoveFavourite.

Вам нужно будет обернуть this. handleRemoveFavourite в анонимный вызов функции. Нравится

          onClick={() => this.handleRemoveFavourite(history)}

и затем примите его как действительный аргумент в вашей функции

handleRemoveFavourite = (history) => {...}

это должно решить

0 голосов
/ 13 сентября 2018
onClick={this.handleRemoveFavourite}
=> 
onClick={()=>this.handleRemoveFavourite(history)}

handleRemoveFavourite = () => {
=>
handleRemoveFavourite = (history) => {
0 голосов
/ 13 сентября 2018

Поскольку вы используете react-router, вы можете использовать withRouter для достижения этой цели.

import { withRouter } from 'react-router-dom'

Оберните имя класса с помощью withRouter.

Например:

вместо того, чтобы делать так:

export default class App .....

Разделить это так:

class App ...

В конце строки:

export default withRouter(App)

Теперь вы можете использовать вот так:

handleRemoveFavourite = () => {
  const { name } = this.props.workout;
  let savedStorage = localStorage.saved.split(",");
  let cleanedStorage = savedStorage.filter(function(e) {
    return e !== name;
  });
  localStorage.setItem("saved", cleanedStorage.toString());
  this.props.history.push("/favourites");
};

Вы можете удалить Route из renderHearIcon():

renderHeartIcon = () => {
    return (
        <Rating
          key={1}
          icon="heart"
          defaultRating={1}
          maxRating={1}
          size="large"
          onClick={this.handleRemoveFavourite}
        />
    );
  };
0 голосов
/ 13 сентября 2018

Изменение на this.props.history.push("/favourites"); должно работать.

EDITED

Ваш компонент находится в маршруте?Если это так, this.props.history будет работать.Я протестировал изменение вашего класса для запуска в моем проекте.

import React from 'react';
import ReactDOM from 'react-dom';
import {
  Container,
  Grid,
  Icon,
  Label,
  Table,
  Header,
  Rating,
  Segment
} from "semantic-ui-react";
 import { Link, Route, BrowserRouter  as Router } from "react-router-dom";

export default class WorkoutComponent extends React.Component {
  static defaultProps = {
      workout: {
          reps: "1,2,3,4",
          workouts: []
      },

  }
  renderChallengeRow = workouts => {
    let { reps } = this.props.workout;
    reps = reps.split(",");

    return workouts.map((item, i) => {
      return (
        <Table.Row key={item.id}>
          <Table.Cell width={9}>{item.name}</Table.Cell>
          <Table.Cell width={7}>{reps[i]}</Table.Cell>
        </Table.Row>
      );
    });
  };

  handleRemoveFavourite = () => {
    const { name } = this.props.workout;
    //let savedStorage = localStorage.saved.split(",");
    // let cleanedStorage = savedStorage.filter(function(e) {
    //   return e !== name;
    // });
    // localStorage.setItem("saved", cleanedStorage.toString());
    this.props.history.push("/favourites");
  };

  renderHeartIcon = () => {
    return (
      <Route
        render={({ history }) => (
          <Rating
            key={1}
            icon="heart"
            defaultRating={1}
            maxRating={1}
            size="large"
            onClick={this.handleRemoveFavourite}
          />
        )}
      />
    );
  };

  render() {
      console.log(this.props)
    const { name, workouts } = this.props.workout;
    const url = `/savedworkout/${name}`;
    return (

          <Grid.Column>
        <Segment color="teal">
          <Link to={url}>
            <Header as="h2" to={url} content="The workout" textAlign="center" />
          </Link>
          <Table color="teal" inverted unstackable compact columns={2}>
            <Table.Body>{this.renderChallengeRow(workouts)}</Table.Body>
          </Table>
          <br />
          <Container textAlign="center">
            <Label attached="bottom">{this.renderHeartIcon()}</Label>
          </Container>
        </Segment>
        <Link to="/generate">
          <Icon name="angle double left" circular inverted size="large" />
        </Link>
      </Grid.Column>
    );
  }
}
ReactDOM.render(
<Router>        
    <Route path="/" component={ WorkoutComponent }/>
</Router>, document.getElementById('root'));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...