Zrobiłem 2 komponenty: 1) zawartość (która wyświetla dane za pomocą fetch ()) 2) paginacji (łącznie 5 stron 16 obiektów na stronę)

Zrobiłem 2 zmienne stanowe zwane start:0 i end:16. Teraz, gdy użytkownik kliknie na numery stron, które chcę wstrzykiwać start i końcowe zmienne stanu z elementu paginacyjnego do składnika treści.

Logika do przechodzenia zmiennych startowych i końcowych do treści jest następująca: początkowo koniec = 16 * 1 (1 jest mnożona, ponieważ strona 1) i Start = End-16 I.E Start = 0

Koniec = 16 * 2 (2 jest mnożone, ponieważ strona 2) i start = End-16 I.E Start = 16

Te zmienne startowe i końcowe są przekazywane .slice() komponentu treści, aby ONCLICK: Page 1 Należy wyświetlić art. 0 do 16 Page 2 Należy wyświetlić art. 16 do 32 i tak dalej do strony 5

Poniżej znajduje się kodeksu paginacji i komponentu treści:

Content.js:

class Content extends Component {

    constructor(props){
        super(props);
        this.state = {
            matches:[],
            loading:true,
            callmatchinfo: false,
            matchid:''
        };
    }

    componentDidMount(){
        fetch('api/matches')
        .then(res => res.json())
        .then(res => {
      console.log(res)
      this.setState({
        matches:res.slice(this.props.start,this.props.end),  <---add new start and end everytime we click on new page number
        loading:false
      });
    })
    }

  viewstats(matchid){
    this.setState({
        callmatchinfo: true,
        matchid: matchid
    });
  }

  rendermatchinfo(){
    return <Matchinfo matchid={this.state.matchid} />
  }

    renderMatches() {
        return this.state.matches.map(match => {
            return (
                <div className="col-lg-3">
                    <div id="content">
                        <p className="match">MATCH {match.id}</p>
                        <h4>{match.team1}</h4>
                        <p>VS</p>
                        <h4>{match.team2}</h4>
                        <div className="winner">
                            <h3>WINNER</h3>
                            <h4>{match.winner}</h4>
                        </div>
                        <div className="stats">
                            <button type="button" onClick= {()=>{this.viewstats(match.id)}} className="btn btn-success">View Stats</button>
                        </div>
                    </div>
                </div>
            );
        })
    }

    render() {

        if (this.state.loading) {
            return <img src="https://upload.wikimedia.org/wikipedia/commons/b/b1/Loading_icon.gif" />
        }
        else if(this.state.callmatchinfo){
        return <Matchinfo match_id={this.state.matchid} />
        }

    return (
      <div>
          <div className="row">
            {this.renderMatches()}
              </div>
          <div className="row">
            {this.state.callmatchinfo ? this.rendermatchinfo() : ''}
          </div>
      </div>
    );
  }
}

export default Content;

Paginacja.js:

class Pagination extends Component {

    constructor(props){
        super(props)
        this.state = {
            start:0,
            end:16
        };
    }

    handleClick(){
        this.setState{
            end:getpagenumber()*16,
            start:end-16
        }
    }

    getpagenumber(val){
        return val;
    }


  render() {
    let{start,end} = this.state;

    return (
      <div>
        <Content/>
          <div className="container">                 
              <ul className="pagination">
               <li {this.getpagenumber(1)} onClick={this.handleClick}><a href="#">1</a></li>
                <li {this.getpagenumber(2)} onClick={this.handleClick}><a href="#">2</a></li>
                <li {this.getpagenumber(3)} onClick={this.handleClick}><a href="#">3</a></li>
                <li{this.getpagenumber(4)} onClick={this.handleClick}><a href="#">4</a></li>
                <li{this.getpagenumber(5)} onClick={this.handleClick}><a href="#">5</a></li>
              </ul>
          </div>
      </div>
    );
  }
}

export default Pagination;

Zrzut ekranu, który wyświetla artykuły do 16 lat, co koniec = 16: Wprowadź opis obrazu tutaj

2
stone rock 29 styczeń 2018, 19:52

4 odpowiedzi

Najlepsza odpowiedź

Potrzebujesz elementu macierzystego do komunikowania dwóch składników, na przykład:

class ParentComponent extends Component {
    state = {
        start: 0,
        end: 16,
    };

    onChangePagination = (start, end) => {
        this.setState({
            start,
            end,
        });
    };

    render() {
        const { start, end } = this.state;
        return (
            <div>
                <Content start={start} end={end} />
                <Pagination
                    onChange={this.onChangePagination} />
            </div>
        );
    }
}

Jest jeszcze jedna zmiana, którą musisz zrobić w komponencie paginacji, a to ma zadzwonić do wywołania zwrotów onChange po zmianie wartości.

handleClick() {
    const end = (getpagenumber() * 16);
    const start = (end - 16);
    this.setState({
        end: end,
        start: start,
    });
    this.props.onChange(start, end);
}


renderMatches() {
    // Slide matches before looping, props will have the
    // values from the pagination component.
    return this.state.matches.slice(this.props.start, this.props.end)
        .map(match => (
            <div className="col-lg-3">
                <div id="content">
                    <p className="match">MATCH {match.id}</p>
                    <h4>{match.team1}</h4>
                    <p>VS</p>
                    <h4>{match.team2}</h4>
                    <div className="winner">
                        <h3>WINNER</h3>
                        <h4>{match.winner}</h4>
                    </div>
                    <div className="stats">
                        <button
                            type="button"
                            onClick={ () => this.viewstats(match.id) }
                            className="btn btn-success">
                            View Stats</button>
                    </div>
                </div>
            </div>
        )
    );
}

Prawdopodobnie może chcesz usunąć lokalny stan z komponentu paginacyjnego, naprawdę tego nie potrzebujesz.

3
bignose 20 październik 2018, 02:58

Crysfel ma najprostsze prawidłowe rozwiązanie, w którym potrzebujesz komponentu macierzystego do zarządzania danymi i przekazuje go swoim dzieciom jako rekwizyty, ale jest inny sposób, który nadaje się lepiej do większych projektów.

Jeśli tylko się uczą się, lub robisz coś małego, zdecydowanie nie używaj go, ale Redux to inny sposób.

Mówiąc prosto, jest to wysoce wyrafinowane wiadro, w którym umieścić swój stan. Teraz, zamiast komponentów dbających o to, jakie jest ich własne państwo, umieszczasz stan nie-prezentacyjny w sklepie Redux, a składniki odczytywane z sklepu z selektorami.

W twoim przypadku wystrzeliłbyś akcję, gdy Pagination jest klikany, aby zmienić sklep, co spowodowałoby, że komponenty słuchania dla dowolnych danych zostanie zmieniony na aktualizację.

2
Adam Barnes 29 styczeń 2018, 17:35

Jeśli chcesz przejść start i end propy, po prostu to zrobić:

....
render() {
    let{start,end} = this.state;

    return (
      <div>
        <Content start={start} end={end} />

.....

Powinno to odpowiedzieć na Twoje konkretne pytanie, jak przejść rekwizyty do Content składnika.

Może to pomóc, ale myślę, że powinieneś wziąć pod uwagę niektórych refaktora kodu.

1
toufek khoury 29 styczeń 2018, 17:13

Musisz przejść funkcję, która aktualizuje stan z Content do Pagination:

Przenieś ten kod do oddzielnej funkcji w Content:

updatePage(start, end) {
    fetch('api/matches')
        .then(res => res.json())
        .then(res => {
            console.log(res)
            this.setState({
                // Add new start and end everytime we click on new page number.
                matches: res.slice(start, end),
                loading: false,
            });
        });
}

Następnie przekazać to jako rekwizyt do Pagination:

<Pagination updatePage={this.updatePage} />

Następnie za każdym razem aktualizujesz stronę w Pagination, zadzwoń this.props.updatePage:

handleClick() {
    const end = this.getpagenumber() * 16;
    const start = end - 16;
    this.setState({
        end,
        start,
    });
    this.props.updatePage(start, end);
}

AKTUALIZACJA:

Prosta aktualizacja do Content, aby tylko pobrać wszystkie dane jednorazowe, a następnie używać rekwizytów do pokrojonego dopasowania na każdy render:

class Content extends Component {

    constructor(props){
        super(props);
        this.state = {
            matches: [],
            loading: true,
            callmatchinfo: false,
            matchid: '',
        };
    }

    componentDidMount() {
        fetch('api/matches')
            .then(res => res.json())
            .then(res => {
                // On mount, load all data and save it in state.
                this.setState({
                    allData: res,
                    loading: false,
                });
            });
    }

    renderMatches() {
        // Here we use slice on all the data and only return
        // 15 matches at a time for rendering.
        return this.state.allData.slice(this.props.start, this.props.end)
            .map(match => (
                <div className="col-lg-3">
                    <div id="content">
                        <p className="match">MATCH {match.id}</p>
                        <h4>{match.team1}</h4>
                        <p>VS</p>
                        <h4>{match.team2}</h4>
                        <div className="winner">
                            <h3>WINNER</h3>
                            <h4>{match.winner}</h4>
                        </div>
                        <div className="stats">
                            <button
                                type="button"
                                onClick={
                                    () => { this.viewstats(match.id) }
                                }
                                className="btn btn-success">
                                View Stats</button>
                        </div>
                    </div>
                </div>
            );
        })
    }

    render() {...}
}

export default Content;
1
bignose 20 październik 2018, 03:05