reactjs - 如何在 ReactJS 中执行下拉状态的突变?
问题描述
我想在我的下拉列表中选择一个项目时更改状态,但是如果不再次单击就不会更改的错误发生。
我知道有相关的问题,但我的代码是一个特例。
与我的两个下拉列表中的这张图片相同的事情发生在我身上。
我更改了“Mes”,但在您返回并选择另一个值之前它不起作用。在那里,我刚刚更改为“第 4 个月”。
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import format from 'date-fns/format';
import gql from 'graphql-tag';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Link } from 'react-router-dom';
import { graphql } from 'react-apollo';
import '../../../node_modules/bootstrap/dist/css/bootstrap.css';
import './style.css';
import {
ButtonDropdown,
DropdownToggle,
DropdownMenu,
DropdownItem,
} from 'reactstrap';
import axios from 'axios';
import TituloSmall, { types } from '../TituloSmall';
const query0 = gql`
query postsDiaComoHoy($dia: Int!, $mes: Int!) {
posts(first: 2, dia: $dia, mes: $mes, categoria: 28) {
rows {
id
fecha_dia_hoy
imagen_intro
titulo
introtext
autor
fulltext
fulltext2
imagen_banner
categoria {
id
}
tags {
id
titulo
}
}
count
}
}
`;
const renderTagItem = item => {
const { id, titulo } = item;
return (
<Link key={id} to={`/tags/${id}/`}>
<div className="tag">{titulo}</div>
</Link>
);
};
const removeTagHtml = valor => valor.replace(/(<([^>]+)>)/g, '');
const removerTwitter = valor => valor.replace(/- @\w+/g, '');
let updated = 0;
let dates = format(Date(), 'D');
let month = format(Date(), 'M');
export class DayScreen extends Component {
constructor(props) {
super(props);
this.state = {
data: this.props,
currentIndex: 0,
sortItem1: month,
sortItem2: dates,
cantidadMeses: [
'Enero',
'Febrero',
'Marzo',
'Abril',
'Mayo',
'Junio',
'Julio',
'Agosto',
'Septiembre',
'Octubre',
'Noviembre',
'Diciembre',
],
diasMes: [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
],
};
}
state = {
items: [],
};
componentDidUpdate() {
this.getArticles();
updated = 0;
}
getArticles = async () => {
const changeArticles = `
{
posts(first: 3, dia: ${this.state.sortItem2}, mes: ${month}) {
rows {
id
fecha_dia_hoy
imagen_intro
titulo
introtext
autor
views
fulltext
fulltext2
imagen_banner
categoria {
id
}
tags{
id
titulo
}
}
count
}
}
`;
if (updated) {
try {
const response = await axios.get(
`http://localhost:4000/graphql/?query=${changeArticles}`,
) .then(response => {
this.setState(() => ({
items: response.data.data.posts.rows,
}));
let { data } = this.props;
const { items } = this.state;
data.posts.rows = items;
return response;
});
// Log the response so we can look at it in the console
// Set the data to the state
} catch (error) {
// If there's an error, set the error to the state
// this.setState(() => ({ error }));
console.log(error);
// console.log(this.state.error);
}
}
};
selectIndex = direction => {
const { currentIndex } = this.state;
const {
data: {
posts: { count },
},
} = this.props;
let nexIndex = currentIndex + direction;
nexIndex = nexIndex < 0 ? count - 1 : nexIndex;
nexIndex = nexIndex >= count ? 0 : nexIndex;
this.setState({ currentIndex: nexIndex });
};
monthSelected() {
const { sortItem1, sortItem2, dropdownOpen1 } = this.state;
this.setState({
dropdownOpen1: !dropdownOpen1,
});
if (dropdownOpen1) {
month = sortItem1;
dates = sortItem2;
updated = 1;
}
}
dateSelected() {
const { sortItem1, sortItem2, dropdownOpen2 } = this.state;
this.setState({
dropdownOpen2: !dropdownOpen2,
});
if (dropdownOpen2) {
month = sortItem1;
dates = sortItem2;
updated = 1;
}
}
onDiasChanged=(e)=>{
this.setState({sortItem2:[...e.currentTarget.innerHTML]});
}
onMesChanged=(e)=>{
this.setState({sortItem1:[...e.currentTarget.innerHTML]});
}
render() {
const { data } = this.props;
if (data.loading) {
return <div>Loading...</div>;
}
if (data.error) {
return <div>{data.error.message}</div>;
}
if (data.posts.rows.length <= 0) {
return <div>Nada que mostrar...</div>;
}
const {
data: {
posts: { rows },
},
} = this.props;
this.items = this.props.data.posts.rows;
const {
currentIndex,
sortItem1,
cantidadMeses,
sortItem2,
dropdownOpen1,
dropdownOpen2,
diasMes,
} = this.state;
const item = rows[currentIndex] ? rows[currentIndex] : rows[0];
const html = item.fulltext + item.fulltext2;
const image = `${process.env.REACT_APP_IMG_BASE}${item.imagen_intro ||
item.imagen_banner}`;
data.variables.mes = sortItem1;
data.variables.dia = sortItem2;
return (
<div className="containerDiaComoHoyNoticia">
<div className="box">
<span />
<span />
<div className="mesTexto">{cantidadMeses[sortItem1 - 1]}</div>
<div className="diaTexto">{sortItem2}</div>
</div>
<div>
<div className="textoContainer">
<div className="tituloDiaComoHoyNoticia">
{'BUSCA QUE OCURRIÓ EL DÍA QUE TU QUIERAS EN EL FÚTBOL'}
</div>
<div className="separatorLinea" />
<div className="listaMesDia">
<span className="circuloMesDia">1</span>
<span>Mes</span>
<ButtonDropdown
isOpen={dropdownOpen1}
toggle={() => {
this.monthSelected();
}}>
<DropdownToggle color="white" caret>
{sortItem1}
</DropdownToggle>
<DropdownMenu>
{cantidadMeses.map((items, i) => (
<DropdownItem
dropDownValue="Mes"
dropDownValue="Mes" onClick={this.onMesChanged}>
{i + 1}
</DropdownItem>
))}
</DropdownMenu>
</ButtonDropdown>
<span className="circuloMesDia">2</span>
<span>Dia</span>
<ButtonDropdown
isOpen={dropdownOpen2}
toggle={() => {
this.dateSelected();
}}>
<DropdownToggle caret>{sortItem2}</DropdownToggle>
<DropdownMenu>
{diasMes.map(i => (
<DropdownItem
dropDownValue="Mes" onClick={this.onDiasChanged}>
{i}
</DropdownItem>
))}
</DropdownMenu>
</ButtonDropdown>
</div>
</div>
</div>
{rows.map(itemArticulo => (
<div className="listaNoticiasContenido">
<img
alt={itemArticulo.titulo}
src={process.env.REACT_APP_IMG_BASE + itemArticulo.imagen_intro}
className="listaNoticiasImagen"
/>
<div className="rectanguloIconoPlay" />
<div className="contenidoArticulo">
<div className="tituloArticulo"><a href="#" onClick = {this.state.currentIndex = 1}>{itemArticulo.titulo}</a></div>
<div className="descripcionArticulo">
{removeTagHtml(itemArticulo.introtext)}
</div>
<div className="escritor">
<div className="nombreAutor">
<div>
<FontAwesomeIcon icon="user-circle" />
<span className="autorArticulo">
{removerTwitter(itemArticulo.autor) || 'Sin autor'}
</span>
<FontAwesomeIcon icon="eye" />
<span className="vistasTotalesArticulos">
{itemArticulo.views}
</span>
<FontAwesomeIcon icon="calendar" />
<span className="cantidadArticulosEscritos">
{itemArticulo.fecha_dia_hoy}
</span>
</div>
</div>
</div>
</div>
<div className="separadorArticulos" />
</div>
))}
<h2 className="tituloDescripcion">{item.titulo}</h2>
<div className="titlesContainer">
<TituloSmall
iconName="user-circle"
label={item.autor || 'Sin autor'}
/>
<TituloSmall
iconName="calendar"
label={format(item.fecha_dia_hoy, 'DD/MM/YYYY')}
/>
</div>
<div className="imageIntro">
<img className="imageDescription" src={image} alt={item.titulo} />
<div className="esquinaFigura">
<div className="boxWhite">
<span />
<span />
<div className="mesTextoBoxWhite">
{cantidadMeses[sortItem1 - 1]}
</div>
<div className="diaTextoBoxWhite">{sortItem2}</div>
</div>
</div>
</div>
<article dangerouslySetInnerHTML={{ __html: html }} />
<TituloSmall iconName="tags" label="Tags" type={types.BIG} />
{item.tags.map(itemsTags => renderTagItem(itemsTags))}
</div>
);
}
}
DayScreen.propTypes = {
data: PropTypes.shape({
loading: PropTypes.bool.isRequired,
currentSortItem: PropTypes.string.isRequired,
error: PropTypes.shape({ message: PropTypes.string }),
}).isRequired,
};
DayScreen.defaultProps = {};
const queryOptions = {
options: () => ({
variables: {
dia: dates,
mes: month,
},
}),
};
export default graphql(query0, queryOptions)(DayScreen);
我希望在不按双击的情况下进行状态更改,并且我在图像中显示的延迟会发生。
谢谢你的帮助!
解决方案
You have directly mutated the state
and not setting the state using setState
method so your render
method will not be called at the time of selection and because of it, you will not getting the change immediately once your render method will be call you will get those changes. so your dropdown implementation should be like.
onMessChanged=(e)=>{
this.setState({sortItem2:e.currentTarget.innerHTML});
}
<DropdownMenu>
{diasMes.map(i => (
<DropdownItem
dropDownValue="Mes"
onClick={this.onMessChanged}>
{i}
</DropdownItem>
))}
</DropdownMenu>
As here you are using the reactstrap
so it might be possible that your event target may be different so you have to use currentTarget
the currentTarget
refers to the element that the event listener directly attached to while the target
still refers to the specific element where we clicked.
推荐阅读
- android-constraintlayout - 如何解决约束布局中缺少约束的问题
- entity-framework - ASP.NET Core:获取外键时出现 NullReferenceException
- twilio - 呼叫转移和被叫号码
- unity3d - 如何修复 Unity3d 中的“导入音频剪辑时出错...”错误
- groovy - 查找以 x 开头的目录(Groovy)
- sharepoint - 有什么方法可以使 SharePoint 自定义客户端 Web 部件响应
- subdomain - 如何使用子域进行网站预览?
- maven - 包含多个 SLF4J
- node.js - 是否可以通过 get 或 post 请求连接到 socket.io?
- r - 在bookdown中:避免宽表被截断