【问题标题】:React click on item to show details反应单击项目以显示详细信息
【发布时间】:2018-12-01 12:20:00
【问题描述】:

我是 React 新手,我正在尝试与 swapi API 进行交互。 我想获取电影列表(电影标题列表),当我单击标题以显示来自 json 对象的 opening_crawl 时。 我设法将电影标题排列成一个数组。我不知道如何从这里开始。

这是我的代码:

class StarWarsApp extends React.Component {
  render() {
    const title = "Star Wars";
    const subtitle = "Movies";
    return (
      <div>
        <Header title={title} />
        <Movies />
      </div>
    );
  }
}

class Header extends React.Component {
  render() {
    return (
      <div>
        <h1>{this.props.title}</h1>
      </div>
    );
  }
}

class Movies extends React.Component {
  constructor(props) {
    super(props);
    this.handleMovies = this.handleMovies.bind(this);
    this.state = {
      movies: []
    };
    this.handleMovies();
  }

  handleMovies() {
    fetch("https://swapi.co/api/films")
      .then(results => {
        return results.json();
      })
      .then(data => {
        console.log(data);
        let movies = data.results.map(movie => {
          return <div key={movie.episode_id}>{movie.title}</div>;
        });

        this.setState(() => {
          return {
            movies: movies
          };
        });
      });
  }
  render() {
    return (
      <div>
        <h1>Episodes</h1>
        <div>{this.state.movies}</div>
      </div>
    );
  }
}

ReactDOM.render(<StarWarsApp />, document.getElementById("app"));

【问题讨论】:

    标签: javascript reactjs api


    【解决方案1】:

    要遍历电影,请在渲染方法中添加:

    render(){
      return (
        <div>
          <h1>Episodes</h1>
          {
            this.state.movies.map((movie, i) => {
              return (
                <div className="movie" onClick={this.handleClick} key={i}>{movie.title}
                  <div className="opening">{movie.opening_crawl}</div>
                </div>
              );
            })
          }
        </div>
      );
    }
    

    将此方法添加到您的电影组件中,以便在点击时将活动类添加到具有“电影”类名的 DIV:

    handleClick = event => {
      event.currentTarget.classList.toggle('active');
    }
    

    将此 css 包含到您的项目中:

    .movie .opening {
      display: none;
    }
    
    .active .opening {
      display: block
    }
    

    【讨论】:

    • 谢谢@Jihlavanka ,这让我们有所启发!我想我需要 webpack 在我的应用程序中包含 css??
    • @Danae 我使用 create-react-app 所以我可以在 React 组件中写 import "./mystyles.css"
    • 我确实也使用过 create-react-app 和 babel。 Babel 将其转换为“require”,我得到一个 ReferenceError 。
    【解决方案2】:

    获取数据后,只需将其保持在您的状态,然后使用您的组件或 JSX 中的片段。不要从您的 handleMovies 方法返回一些 JSX,只需在那里执行 setState 部分。另外,我建议使用生命周期方法(或钩子 API,如果您使用功能组件)来触发获取。顺便说一句,除非您需要状态或生命周期方法,否则不要使用类组件。

    之后,您可以通过映射电影状态在您的渲染方法中渲染您的标题。此外,您可以为您的 opening_crawls 部分放置一个位置,并使用条件运算符对其进行渲染。这种情况会随着点击而改变。为此,您有一个额外的状态属性并将电影ids 保留在那里。通过单击,您可以将id 值设置为true 并显示爬网。

    这是一个简单的工作示例。

    const StarWarsApp = () => {
      const title = "Star Wars";
      const subtitle = "Movies";
      return (
        <div>
          <Header title={title} />
          <Movies />
        </div>
      );
    }
    
    const Header = ({ title }) => (
      <div>
        <h1>{title}</h1>
      </div>
    );
    
    class Movies extends React.Component {
      state = {
        movies: [],
        showCrawl: {}
      };
    
      componentDidMount() {
        this.handleMovies();
      }
    
      handleMovies = () =>
        fetch("https://swapi.co/api/films")
          .then(results => results.json())
          .then(data => this.setState({ movies: data.results }));
    
      handleCrawl = e => {
        const { id } = e.target;
        this.setState(current => ({
          showCrawl: { ...current.showCrawl, [id]: !current.showCrawl[id] }
        }));
      };
    
      render() {
        return (
          <div>
            <h1>Episodes</h1>
            <div>
              {this.state.movies.map(movie => (
                <div
                  key={movie.episode_id}
                  id={movie.episode_id}
                  onClick={this.handleCrawl}
                >
                  {movie.title}
                  {this.state.showCrawl[movie.episode_id] && (
                    <div style={{ border: "1px black solid" }}>
                      {movie.opening_crawl}
                    </div>
                  )}
                </div>
              ))}
            </div>
          </div>
        );
      }
    }
    
    ReactDOM.render(<StarWarsApp />, document.getElementById("root"));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
    <div id="root"></div>

    我在目标div 上使用idevent 对象中取回它。我不太喜欢这种方法,但为了清楚起见,我使用了这个。您可以重构它并创建另一个组件,然后您可以在那里传递epoisde_id 并处理setState 部分。或者您可以使用数据属性而不是id

    【讨论】:

      猜你喜欢
      • 2018-07-31
      • 2019-11-09
      • 2019-07-21
      • 2017-06-08
      • 2020-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多