css - 防止页面跳转按钮点击? ReactJS

标签 css reactjs onclick page-jump

我有一个 ShowcaseMovie 组件,它在 componentDidMount() 上获取数据并将其设置为状态。该组件渲染 Card 组件以显示数据以及四个按钮元素 upcoming , top_rated , popularnow_playing这允许用户在相关数据之间切换。每个按钮都有一个 onClick 事件,它调用 changeFilter并设置状态 currentFilter到选定的键。

问题:当点击过滤器按钮时,有时页面会跳到顶部(如果它还没有)。我试图找到解决方案,但我似乎无法理解发生了什么。任何建议都会有很大帮助,在此先感谢您。

更新:当没有为具有动态子元素的元素设置高度时,似乎会发生此问题。如果我将 ShowcaseMovie 上的高度设置为较大的值,例如 height: 200vh它消失了。

我相信我已经解决了我的问题,但很想听听其他关于为什么会发生这种情况的想法以及其他一些解决方法。当您不知道要渲染多少内容(或该内容的高度)时,很难为父级设置高度。 min-height会有所帮助,但仍然是一种快速修复。

ShowcaseMovie.js

import React, { Component } from "react";
import Card from "./Card";
import "../css/ShowcaseMovie.css";
import { v4 as uuidv4 } from "uuid";
import { formatString, buildMovieState } from "../utilities";

class ShowcaseMovie extends Component {
  static defaultProps = {
    filterNames: ["upcoming", "popular", "now_playing", "top_rated"]
  };

  constructor(props) {
    super(props);
    this.state = {
      upcoming: [],
      now_playing: [],
      popular: [],
      top_rated: [],
      currentFilter: this.props.filterNames[0]
    };
  }

  changeFilter = e => {
    e.preventDefault();
    const type = e.target.name;
    this.setState({ currentFilter: type });
  };

  componentDidMount() {
    this.props.filterNames.map(name => this.fetchMovies(name));
    // setInterval(() => {
    //   this.timeoutFilter();
    // }, 10000);
  }

  async fetchMovies(type) {
    try {
      const res = await fetch(
        `url`
      );
      const data = await res.json();
      if (data) {
        this.setState(state => ({
          ...state,
          [type]: buildMovieState(data)
        }));
      }
    } catch (error) {
      console.log(error);
    }
  }

  render() {
    const { currentFilter } = this.state;
    const movies = this.state[currentFilter].map((movie, i) => (
      <Card key={uuidv4()} movie={movie} index={i} />
    ));
    const buttons = this.props.filterNames.map(name => (
      <button
        type="button"
        key={name}
        name={name}
        className={`ShowcaseMovie-btn ${
          currentFilter === name ? "active" : ""
        }`}
        disabled={currentFilter === name}
        onClick={this.changeFilter}>
        {formatString(name)}
      </button>
    ));

    return (
      <section className="ShowcaseMovie">
        <div className="ShowcaseMovie-container">
          <h2 className="ShowcaseMovie-header">Movies</h2>
          <div className="ShowcaseMovie-btn-container">{buttons}</div>
        </div>
        <div className="ShowcaseMovie-grid">{movies}</div>
      </section>
    );
  }
}

ShowcaseMovie.css
.ShowcaseMovie {
  padding: 4rem 10%;
}

.ShowcaseMovie-container {
  position: relative;
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 2rem;
}

.ShowcaseMovie-button-container {
  display: flex;
  justify-content: center;
  align-items: center;
}

.ShowcaseMovie-container::after {
  content: "";
  background-color: #64b5f6;
  height: 80%;
  width: 6px;
  left: 0;
  position: absolute;
  border-radius: 1px;
}

.ShowcaseMovie-header {
  font-size: 3rem;
  font-weight: 200;
  margin: 0 5rem;
}

.ShowcaseMovie-btn {
  outline: none;
  border: none;
  background-color: transparent;
  font-size: 1.6rem;
  font-weight: 500;
  letter-spacing: 1px;
  padding: 1rem;
  margin-left: 4rem;
  color: white;
  opacity: 0.5;
  cursor: pointer;
  transition-property: opacity;
  transition-duration: 300ms;
  transition-timing-function: ease;
}

.ShowcaseMovie-btn:hover {
  opacity: 1;
  transition-property: opacity;
  transition-duration: 300ms;
  transition-timing-function: ease;
}

.ShowcaseMovie-btn.active {
  opacity: 1;
  cursor: auto;
  color: #64b5f6;
}

.ShowcaseMovie-grid {
  display: grid;
  gap: 3rem;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
}

Card.js
import React, { Component } from "react";
import "../css/Card.css";

class Card extends Component {
  render() {
    const { title, poster_path } = this.props.movie;
    const style = { animationDelay: `${80 * this.props.index}ms` };
    return (
      <div className="Card">
        <div className="Card-inner" style={style}>
          <img
            src={`https://image.tmdb.org/t/p/w500/${poster_path}`}
            alt=""
            className="Card-img"
          />
          <p className="Card-name">{title}</p>
        </div>
      </div>
    );
  }
}

export default Card;

Card.css
.Card {
  display: block;
  transition: transform 300ms ease;
}

.Card:hover {
  transform: translateY(-5px);
  transition: transform 300ms ease;
}

.Card-inner {
  position: relative;
  display: block;
  cursor: pointer;
  height: 100%;
  opacity: 0;
  animation-name: moveUp;
  animation-duration: 500ms;
  animation-delay: 50ms;
  animation-timing-function: ease;
  animation-fill-mode: forwards;
}

.Card-inner::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-image: linear-gradient(transparent, rgba(33, 47, 61, 0.8));
  border-bottom-left-radius: 2px;
  border-bottom-right-radius: 2px;
  z-index: 100;
  opacity: 1;
  transition: opacity 300ms ease;
}

.Card-inner:hover::after {
  opacity: 0;
  transition: opacity 300ms ease;
}

.Card-inner::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-image: linear-gradient(transparent, rgba(100, 180, 246, 0.6));
  border-bottom-left-radius: 2px;
  border-bottom-right-radius: 2px;
  z-index: 100;
  opacity: 0;
  transition: opacity 300ms ease;
}

.Card-inner:hover::before {
  opacity: 1;
  transition: opacity 300ms ease;
}

.Card-img {
  display: block;
  position: relative;
  object-fit: cover;
  max-width: 100%;
  min-height: 100%;
  z-index: 0;
  border-radius: 2px;
}

.Card-name {
  position: absolute;
  bottom: 0;
  left: 0;
  margin: 0 2rem 2rem 2rem;
  z-index: 150;
  font-weight: 400;
  text-transform: uppercase;
  font-size: 1.4rem;
  letter-spacing: 2px;
}

@keyframes moveUp {
  0% {
    transform: translateY(5rem);
  }

  100% {
    transform: translateY(0);
    opacity: 1;
  }
}

实用程序.js
export const formatString = name => {
  return name
    .replace("_", " ")
    .split(" ")
    .map(w => w[0].toUpperCase() + w.slice(1))
    .join(" ");
};

export const buildMovieState = data => {
  if (data.results) {
    const movies = data.results.filter(
      d => d.backdrop_path && d.id && d.title && d.poster_path
    );
    return movies.length > 10 ? movies.slice(0, 10) : movies;
  } else {
    return [];
  }
};

最佳答案

我可以通过返回 false 来阻止这种情况的发生。来自 onClick称呼。像这样:

onClick={
   doSomething()
   return false
}

关于css - 防止页面跳转按钮点击? ReactJS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60846192/

相关文章:

java - OnItemClickListener 无法识别

css - 尝试让 jQuery Mobile 元素在 TouchStart 上突出显示

javascript - React 和 Redux 中的事件监听器内存泄漏

html - 流体设计的 float 中断

reactjs - 在 React 中动态加载 Material-UI 图标

javascript - 读取javascript脚本index.html公共(public)文件夹中的类react js

javascript - 我怎样才能用 OnClientClick 做到这一点

javascript - 如何通过多个 EJS 数据字段的 onClick 填充多个表单字段

c# - 带有动态单选按钮的附加 html 标签

html - CSS 列无法正常工作