#javascript #reactjs #redux #react-redux #mern
#javascript #reactjs #redux #реагировать-redux #мерн
Вопрос:
Редактировать
Компонент, в котором это состояние не отображается, называется TournamentShow , который вызывает состояние и любые функции, которые мне нужно использовать для отображения страницы.
Вложенный в него условный вызов одной из 3 страниц, основанный на
Tournament.Status === "Open"
,
Tournament.Status === "Closed"
, и
Tournament.Status === "Complete"
Турнирное шоу:
import React, { Component } from 'react';
import { SignUpPage, HostUI, StartBracket, Results } from './TournamentScreens';
import {
showTournament,
addParticipant,
closeTournament,
shuffleParticipants
} from '../../actions/tournamentActions';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { Spinner } from 'reactstrap';
class TournamentShow extends Component {
constructor(props) {
super(props);
this.onSignUp = this.onSignUp.bind(this);
this.onStartTournament = this.onStartTournament.bind(this);
this.onShuffleParticipants = this.onShuffleParticipants.bind(this);
};
componentDidMount() {
const id = this.props.match.params.id;
this.props.showTournament(id);
};
static propTypes = {
tournament: PropTypes.object.isRequired,
auth: PropTypes.object.isRequired
};
onSignUp(tournamentId, user) {
this.props.addParticipant(tournamentId, user);
};
onShuffleParticipants(array) {
let currentIndex = array.length, temporaryValue, randomIndex;
while(0 !== currentIndex) {
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
};
onStartTournament(tourneyId) {
const { participants } = this.props.tournament.showTournament;
// Randomize participants
let reorderedParticipants = [];
const shuffledParticipants = this.onShuffleParticipants(participants);
shuffledParticipants.forEach(participant => {
reorderedParticipants.push(participant);
});
// Send new participants list to backend
this.props.shuffleParticipants(tourneyId, reorderedParticipants);
// Set Status to "Closed"
this.props.closeTournament(tourneyId);
};
render() {
console.log(this.props.tournament)
const loading = this.props.tournament.loading || !this.props.tournament.showTournament;
if(loading) {
return <Spinner color="light" />
} else {
if(this.props.tournament.showTournament.status === "Complete") {
return (
<Results />
);
} else if(this.props.tournament.showTournament.status === "Closed") {
return (
<div>
<HostUI
tournament={this.props.tournament.showTournament}
/>
<StartBracket
tournament={this.props.tournament.showTournament}
/>
</div>
);
} else {
return (
<SignUpPage
tournament={this.props.tournament.showTournament}
auth={this.props.auth}
onSignUp={this.onSignUp}
onStartTournament={this.onStartTournament}
/>
);
}
};
};
};
const mapStateToProps = state => ({
tournament: state.tournament,
auth: state.auth
});
export default connect(mapStateToProps,
{ showTournament, addParticipant, closeTournament, shuffleParticipants }
)(TournamentShow);
Экраны показа турниров:
import React from 'react';
import moment from 'moment';
import { TournamentSignUp, StartTournament } from './resources/buttons';
import { TournamentRules } from './resources/rulesets';
import { Button } from 'reactstrap';
import { Link } from 'react-router-dom';
// Status === "Open"
export const SignUpPage = ({ tournament, auth, onSignUp, onStartTournament }) => {
};
// Status === "Closed"
export const HostUI = ({ tournament }) => {
const { players } = tournament.bracket;
return (
<div style={{color:"lightgrey"}}>
<h1>Host UI</h1>
{
players amp;amp; players.map(player => (
<div>
{player.username}
</div>
))
}
</div>
);
};
export const StartBracket = ({ tournament }) => {
const { title, hostedBy, participants } = tournament;
return (
<div className="text-center" style={{color:"lightgrey", backgroundColor: "#333333"}}>
<h1>{ title }</h1>
<h4>By { hostedBy }</h4>
<h4>{participants amp;amp; participants.length}-player bracket</h4>
<br /><Link to="/">Back to Tournaments main page</Link>
</div>
);
};
// Status === "Complete"
export const Results = () => {
};
Status===Closed
показывает оба этих центральных компонента.
HostUI
отображает только players
массив (который только что был обновлен непосредственно перед переключением / повторным отображением состояния)
StartBracket
показывает материал из ShowTournament
, то есть все данные, которые уже были установлены в состоянии
ОРИГИНАЛ —————————
I’ll mark with // comment which case does not work
import {
GET_TOURNAMENTS,
SHOW_TOURNAMENT,
ADD_TOURNAMENT,
ADD_TOURNAMENT_FAIL,
EDIT_TOURNAMENT,
EDIT_TOURNAMENT_FAIL,
DELETE_TOURNAMENT,
TOURNAMENTS_LOADING,
TOURNAMENT_LOADING,
USER_JOINS_TOURNAMENT,
TOURNAMENT_SIGN_UP_FAIL,
TOURNAMENT_STATUS_UPDATE,
TOURNAMENT_STATUS_FAILED,
SHUFFLE_PARTICIPANTS,
SHUFFLE_FAILED
} from '../actions/types';
const initialState = {
tournaments: [],
showTournament: {},
loading: false,
};
export default function(state = initialState, action) {
switch(action.type) {
case GET_TOURNAMENTS:
return {
...state,
tournaments: action.payload,
loading: false
};
case SHOW_TOURNAMENT:
return {
...state,
showTournament: action.payload,
loading: false
};
case ADD_TOURNAMENT:
return {
...state,
tournaments: [action.payload, ...state.tournaments]
};
case DELETE_TOURNAMENT:
return {
...state,
tournaments: state.tournaments.filter(tournament => tournament._id !== action.payload)
};
case TOURNAMENTS_LOADING:
case TOURNAMENT_LOADING:
return {
...state,
loading: true
};
case USER_JOINS_TOURNAMENT:
return {
...state,
...state.showTournament.participants.push(action.payload)
};
case TOURNAMENT_STATUS_UPDATE: // Occurs with SHUFFLE_PARTICIPANTS, which doesn't work
return {
...state,
...state.showTournament.status = action.payload
};
case SHUFFLE_PARTICIPANTS: // Does not work
return {
...state,
...state.showTournament.bracket.players.push(action.payload)
}
case EDIT_TOURNAMENT:
case ADD_TOURNAMENT_FAIL:
case EDIT_TOURNAMENT_FAIL:
case TOURNAMENT_SIGN_UP_FAIL:
case TOURNAMENT_STATUS_FAILED:
case SHUFFLE_FAILED:
return {
...state,
}
default:
return state;
};
};
Большая часть этого работает.
Я уверен, что я облажался TOURNAMENT_STATUS_UPDATE
, и SHUFFLE_PARTICIPANTS
, хотя обновление статуса работает так, как задумано.
Это турнирное приложение, на странице показа которого отображаются 3 разных компонента на основе showTournament.status
...
if(loading) {
return <Spinner color="light" />
} else {
if(this.props.tournament.showTournament.status === "Complete") {
return (
<Results />
);
} else if(this.props.tournament.showTournament.status === "Closed") {
return (
<div>
<HostUI
tournament={this.props.tournament.showTournament}
/>
<StartBracket
tournament={this.props.tournament.showTournament}
/>
</div>
);
} else {
return (
<SignUpPage
tournament={this.props.tournament.showTournament}
auth={this.props.auth}
onSignUp={this.onSignUp}
onStartTournament={this.onStartTournament}
/>
);
}
};
Кнопка компонента:
- рандомизирует
Tournament.participants
и отправляет его вTournament.bracket.players
- Наборы
Tournament.status === "Closed"
Это обновляет страницу и Status: "Closed"
правильно отображает страницу.
Проблема в том, что он отображает только то, что я уже загрузил в состояние. (материал из SHOW_TOURNAMENT
)
bracket.players
Массив, в который я отправил рандомизированный список пользователей, не отображается, пока я не обновлю страницу.
Ответ №1:
Вам нужно мелко копировать каждый уровень состояния, которое вы обновляете. Кроме того, ...state.showTournament.bracket.players.push(action.payload)
будет просто пытаться распространить возвращаемое значение push
, которое является просто новой длиной массива. Это не то, что вы хотите.
case TOURNAMENT_STATUS_UPDATE:
return {
...state,
showTournament: {
...state.showTournament,
status: action.payload,
},
};
case SHUFFLE_PARTICIPANTS:
return {
...state,
showTournament: {
...state.showTournament,
bracket: {
...state.showTournatment.bracket,
players: [...state.showTournament.bracket.players, ...action.payload], // spread payload array
},
},
}
Комментарии:
1. Я читал это в документах, но это не дошло. Хорошо, я только что попробовал это. То же самое. Компонент обновляется и показывает следующую страницу (в соответствии со статусом), но мне все равно нужно обновить, чтобы отобразить игроков
2. @Cin88 В каком компоненте состояние не обновляется? Можете ли вы включить этот код компонента и как он связан с вашим хранилищем redux?
3. Спасибо Дрю. Обновил сообщение, чтобы ответить на ваш вопрос
4. @Cin88 Вы убедились, что ваши действия затрагивают redux и reducer? Установлен ли у вас redux-devtools, чтобы проверить, что состояние обновлено до того, что вы ожидаете? Если вы реализуете
componentDidUpdate
функцию, видите ли вы там обновленные реквизиты?5. @Cin88 Отлично! Я также внес изменения в свой ответ. Приветствия.
componentDidUpdate
это просто функция жизненного цикла, вызываемая при обновлении состояния или реквизита, это простое место, где можно просто удалить журнал консоли для всего, что вы хотите проверить при повторной визуализации компонента.
Ответ №2:
Решение Дрю сработало, просто для того, чтобы передать массив в другой массив, синтаксис
players: [...state.showTournament.bracket.players. ...action.payload]
вместо players: [...state.showTournament.bracket.players, action.payload]
Добрый день