当onClick时用参数reactJs setState

IT技术 javascript reactjs jsx
2021-05-13 06:52:37

我正在使用 Reactjs 制作一个简单的相册列表,单击每个项目后,我必须获取该相册的所有照片,所以我想更改状态 (album_Id) .. 问题是我无法更改状态我不知道如何独立加载第二页(显示一个相册的所有照片)。拜托我需要你的帮忙。

这是我的代码(App.js):

import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Link } from 'react-router-dom';
import Photolist from './photolist';
// import logo from './logo.svg';
import './App.css';

class App extends Component {
  constructor(props){
        super(props);
        this.state = {
          currentAlbumId: null,
          CurrentPhotoId: null
        };
        this.updateCurrentAlbum = this.updateCurrentAlbum.bind(this);
    }

  updateCurrentAlbum(id) {
    this.setState({currentAlbumId : id})
  }

  render() {

    const tab_albums = [
      {
        "albumId": 1,
        "id": 1,
        "title": "accusamus beatae ad facilis cum similique qui sunt",
        "url": "http://placehold.it/600/92c952",
        "thumbnailUrl": "http://placehold.it/150/92c952"
      },
      {
        "albumId": 1,
        "id": 2,
        "title": "reprehenderit est deserunt velit ipsam",
        "url": "http://placehold.it/600/771796",
        "thumbnailUrl": "http://placehold.it/150/771796"
      },
      {
        "albumId": 2,
        "id": 66,
        "title": "provident rerum voluptatem illo asperiores qui maiores",
        "url": "http://placehold.it/600/ee0a7e",
        "thumbnailUrl": "http://placehold.it/150/ee0a7e"
      },
      {
        "albumId": 2,
        "id": 67,
        "title": "veritatis labore ipsum unde aut quam dolores",
        "url": "http://placehold.it/600/1279e9",
        "thumbnailUrl": "http://placehold.it/150/1279e9"
      }
    ]; 
    const albumsIds = [];
    
    tab_albums.map((album_model) => {
        return (
            albumsIds.indexOf(album_model.albumId) === -1 ? albumsIds.push(album_model.albumId) : null
        )
    });

    var album_style = {"background": "#cccccc", "marginBottom": "10px", "borderLeft": "5px solid red"};
    var style_div = {"width": "50%", "float": "left"};

    const liste_album = albumsIds.map((alb_id) => {
          return (
            <Router key={alb_id}>
                <li style={album_style} >
                    <Link to={"/photolist/"+alb_id} onClick={() => this.updateCurrentAlbum(alb_id)}>
                    Album : { alb_id }
                    </Link>
                    <Route path="/photolist" component={Photolist}/>
                </li>
            </Router> 
          )
    });
  return (
    <div className="App">
      <div style={style_div}>
         <ul>{liste_album}   </ul>
      </div>
      <div style={style_div}>
        <button>wishlist</button>
      </div>
    </div>
    ); 
  }
}
export default App;

1个回答

似乎您将链接与您认为应该是路由器信息的内容一起呈现,但这实际上并不是它的工作原理

然而,您应该做的是独立渲染链接,并查看您的照片列表中的一项,在您的渲染应用程序中添加匹配的路线。

因此,更改链接的呈现方式,如下所示:

const liste_album = albumsIds.map((alb_id) => {
      return (
            <li style={album_style} key={alb_id}>
                <Link to={"/photolist/"+alb_id}>
                Album : { alb_id }
                </Link>
            </li>
      )
});

删除onClick处理程序,因为这是由Link组件完成的当它导航时,您的应用程序会知道浏览器位置已更改。要显示当前活动路线,您应该像这样更改渲染(请注意,此处定义了路由器,并且您应该只定义模板路径以匹配活动路线或确切路径,具体取决于您的需要)

return (
  <Router>
    <div className="App">
      <div style={style_div}>
        <ul>{liste_album}</ul>
      </div>
      <div style={style_div}>
        <button>wishlist</button>
      </div>
      <Route path="/photolist/:id" render={({match}) => <Photolist alb_id={match.params.id} />
    </div>
  </Router>
  ); 
}

这条线

<Route path="/photolist/:id" render={({match}) => <Photolist alb_id={match.params.id} />

将找到任何具有参数的路径并渲染某个组件。目前我正在传递alb_id,但是您可以选择搜索匹配的相册,并将其传递给 Photolist。

或者,您也可以将路径创建为:

<Route path="/photolist/:id" component={Photolist} />

Photolist使用withRouter高阶函数导出组件(我猜这将是一个专辑),这将使您至少可以从路由器props中获取参数。但是,这在您当前的设置中并不完全有效,因为您的代码似乎将数据与渲染和状态映射混合在一起。这很好,并不完美。您的组件似乎也做得很好。

您应该从刚刚显示的那个组件中创建 3 或 4 个组件,例如,检查此版本的照片列表:

// just some imports matching with the cdn packages
const { Route, withRouter } = ReactRouter;
const { Link } = ReactRouterDOM;
const { createStore, combineReducers } = Redux;
const { Provider, connect } = ReactRedux;
const { Component } = React;

const Router = ReactRouter.MemoryRouter;

const tab_albums = [
  {
    "albumId": 1,
    "id": 1,
    "title": "accusamus beatae ad facilis cum similique qui sunt",
    "url": "http://placehold.it/600/92c952",
    "thumbnailUrl": "http://placehold.it/150/92c952"
  },
  {
    "albumId": 1,
    "id": 2,
    "title": "reprehenderit est deserunt velit ipsam",
    "url": "http://placehold.it/600/771796",
    "thumbnailUrl": "http://placehold.it/150/771796"
  },
  {
    "albumId": 2,
    "id": 66,
    "title": "provident rerum voluptatem illo asperiores qui maiores",
    "url": "http://placehold.it/600/ee0a7e",
    "thumbnailUrl": "http://placehold.it/150/ee0a7e"
  },
  {
    "albumId": 2,
    "id": 67,
    "title": "veritatis labore ipsum unde aut quam dolores",
    "url": "http://placehold.it/600/1279e9",
    "thumbnailUrl": "http://placehold.it/150/1279e9"
  }
]; 

const albumsReducer = (state = tab_albums, action) => {
  // currently not doing anything specials, so just load the albums in the state
  return state;
}

// the store will trigger all changes down to any components intrested in it, thanks to the Provider component
const store = createStore( combineReducers({ albums: albumsReducer }) );

// redux helper to match state to the props, so that components can access the defined properties inside its props
const albumsStateToProps = state => ({ albums: state.albums });

// the album is a purely stateless component, it simply receives the props it should show
const Album = ({ albums, currentAlbumId }) => {
  // get the album based on the passed currentAlbumId
  let album = albums.find(a => {
    return a.id == currentAlbumId;
  });
  return <div>
    <h1>Album: {album.title}</h1>
    <div>
      <a href={album.url} target="_blank"><img src={album.thumbnailUrl} alt="album image" /></a>
    </div>
    <Link to="/">Back to mainpage</Link>
  </div>;
};

const ConnectedAlbum = connect( albumsStateToProps )( Album );

// the location is received thanks to the withRouter higher order function
const PathViewer = ({location}) => {
  return <span>{ location.pathname }</span>;
};

// this creates a new component that extends the props of the PathViewer
const RouterPathViewer = withRouter( PathViewer );

// the overview component will receive the albums through its props, and just needs to map it
const Overview = ( {albums} ) => {
  return <ul>{albums && albums.map( ({id, title}) => <li><Link to={`/album/${id}`}>{ title }</Link></li> ) }</ul>;
};

// the ConnectedOverview gets its props thanks to the albumsStateToProps method defined above
// this means that the Overview component will have access to props.albumns
const ConnectedOverview = connect(albumsStateToProps)(Overview);

// this is the layout component, it enables the routing, and shows the main page
class AlbumViewer extends Component {
  render() {
    return <Router>
      <div>
        <h1>Album viewer</h1>
        <span>Current path: <RouterPathViewer /></span>
        <Route path="/" exact={true} component={ConnectedOverview} />
        <Route path="/album/:id" render={({match}) => {
          return <ConnectedAlbum currentAlbumId={match.params.id} />;
        } }/>
      </div>
    </Router>;
  }
}

// this creates the rendering, where the Provider will rerender components depending on it based on changes on the store
ReactDOM.render( <Provider store={store}><AlbumViewer /></Provider>, document.querySelector('#container') );
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-router/4.2.0/react-router.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-router-dom/4.2.2/react-router-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/5.0.6/react-redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.7.2/redux.min.js"></script>
<div id="container"></div>

我欢迎您完成我制作的小演示,或者如果您可能对设置有疑问,以及为什么需要这么多包来运行这个小应用程序,所以请随意使用它;)