Обновление исходного сообщения: Я понял, что проблема в том, что обновления в состоянии Redux (свойства компонента WaitingRoom) каким-то образом устанавливают все состояние компонента в его исходное состояние. Таким образом, для параметра showmatchingwindow также было установлено значение false. Первоначально после отправки MATCHING_REQUEST и установки для параметра "loading" значения true состояние компонента WaitingRoom по-прежнему оставалось неизменным. Однако после того, как MATCHING_SUCCESS был отправлен и «загрузка» стала ложной, а «buddy» и «chatid» в состоянии Redux были обновлены, все поля в состоянии WaitingRoom каким-то образом были сброшены до своих начальных значений. Это странно и не происходило с другими моими действиями Redux. Мне интересно, может ли кто-нибудь помочь мне объяснить, чем это вызвано. Благодарим вас за терпение и любую помощь, которую вы можете предложить!
Ссылка на репозиторий Github : https://github.com/liu550/salon_project (Компонент WaitingRoom находится в src / components / waitroom. js
/// Ниже оригинальное сообщение ///
Я создаю функцию случайного сопоставления для своего веб-сайта. Вот краткое описание : Я хочу, чтобы окно чата всплывало после успешного сопоставления двух пользователей. В моем состоянии Redux у меня есть (1) «загрузка», (2) «приятель», представляющий идентификатор пользователя, которого наш текущий пользователь сопоставляется с (3) "chatid", представляющим идентификатор документа firestore, в котором хранится история чата между двумя пользователями. Действие startMatching Redux вызывается в компоненте WaitingRoom, который представляет собой веб-страницу, которая дополнительно отображает профили других пользователей Окно чата - это компонент MatchingWindow, которому требуется chatid в качестве реквизита для отображения соответствующей истории чата между двумя пользователями.
Я уверен, что t что мои действия Redux работают нормально, но возникли проблемы при передаче обновленного состояния Redux в мои компоненты React. Ниже приведены 2 подхода, которые я пробовал:
Подход 1 : отображение окна чата внутри модального окна, возвращаемого компонентом WaitingRoom. Как видите, то, что я здесь делаю, - это просто условный рендеринг. Однако при таком подходе модальное окно каким-то образом быстро появилось менее чем на секунду, а затем исчезло вместе с предыдущим модальным окном, в котором пользователи выбирают свои гендерные предпочтения. Проверяя свойства компонента WaitingRoom, я обнаружил, что «buddy» и «chatid» действительно были обновлены. Не следует ли отображать MatchingWindow? Я также попытался просто поставить success> вместо компонента MatchingWindow, и результат был тот же.
Подход 1 (Комната ожидания)
class WaitingRoom extends Component {
state = {
......
}
showMatching = (e) => {
e.preventDefault();
this.setState({
showmatching: true
})
}
handleMatching = (e) => {
e.preventDefault();
this.props.startMatching(this.props.auth.uid, this.props.profile, this.props.profile.gender, this.state.genderpreference);
this.setState({
showmatchingwindow: true
})
}
closeMatching = () => {
this.setState({
showmatching: false
})
}
render() {
const { auth, users, profile, loading, sent, buddy, chatid } = this.props;
return (
<div>
<Button variant="success" onClick={this.showMatching} style={{ fontSize: "large", fontFamily: "Comic Sans MS, cursive, sans-serif"}}>Randomly find a study/work buddy instantly!</Button>
</div>
<Modal show={this.state.showmatching} onHide={this.closeMatching}>
<Modal.Header closeButton></Modal.Header>
<Modal.Body>
<form onSubmit={this.handleMatching}>
Match me with:
<div className="form-inline">
<div className="radio-container">
<label>Male only</label><input type="radio" id="genderpreference" value="Male" onChange={this.handleChange} checked={this.state.genderpreference === "Male"} />
</div>
......
</div>
<button>Start matching</button>
</form>
</Modal.Body>
</Modal>
<Modal show={this.state.showmatchingwindow} onHide={this.closeMatching}>
<Modal.Header closeButton></Modal.Header>
<Modal.Body>
{ loading ? <div class="loader"></div> : null}
{ buddy !== "" && loading === false ? <MatchingWindow chatid=chatid /> : null }
{ buddy === "" && loading === false ? <span>Sorry we cannot help you find a study/work buddy currently</span> : null }
</Modal.Body>
</Modal>
);
}
}
const mapStateToProps = (state) => {
return {
users: state.firestore.ordered.users,
auth: state.firebase.auth,
profile: state.firebase.profile,
loading: state.auth.loading,
sent: state.auth.sent,
buddy: state.auth.buddy,
chatid: state.auth.chatid
}
}
export default compose(
connect(mapStateToProps, {submitTicket, startMatching, groupMessaging}),
firestoreConnect([
{ collection: 'users' }
])
)(WaitingRoom);
Подход 2 : Создайте отдельный компонент MatchingBox, который будет отображать разные элементы / компоненты на основе разных состояний. Однако, когда я использовал этот подход, componentWillReceiveProps () не запускался после изменения состояния Redux, так как console.log (), который я поместил внутри метода, не выполнялся. Это было странно, потому что, как я упоминал в подходе 1, состояние Redux действительно было изменено, когда я проверил реквизиты для компонента WaitingRoom, что означает, что мой код действия и редуктора Redux должен быть в порядке, и он должен работать так же для компонента MatchingBox. также. В результате того, что componentWillReceiveProps () не был запущен, chatid, который я передал компоненту MatchingWindow, был пустой строкой, что является проблемой c. Я попробовал componentDidUpdate (), и он тоже не сработал.
Подход 2 (Комната ожидания)
class WaitingRoom extends Component {
render() {
return (
......All the same except for replacing the second Modal with:
{ this.state.showmatchingwindow ? <MatchingBox /> : null }
);
}
}
Подход 2 (MatchingBox)
class MatchingBox extends Component {
state = {
loading: true,
chatid: "",
buddy: []
}
componentDidMount() {
console.log(this.props.loading);
console.log(this.props.chatid);
console.log(this.props.buddy);
this.setState({
loading: this.props.loading,
chatid: this.props.chatid,
buddy: this.props.buddy
})
}
componentWillReceiveProps() {
console.log(this.props.chatid);
console.log(this.props.buddy);
this.setState({
loading: this.props.loading,
chatid: this.props.chatid,
buddy: this.props.buddy
})
}
render() {
let box;
if (this.props.loading === true) {
box = <div class="loader"></div>
}
else {
if (this.props.buddy !== "") {
box = <div>
<MatchingWindow chatid={this.state.chatid} />
</div>
}
else {
box = <span>Sorry</span>
}
}
return (
<div>
{box}
</div>
);
}
}
const mapStateToProps = (state) => {
return {
auth: state.firebase.auth,
loading: state.auth.loading,
chatid: state.auth.chatid,
buddy: state.auth.buddy,
profile: state.firebase.profile
};
}
export default connect(mapStateToProps)(MatchingBox);
Как указано выше, я почти уверен, что мои действия с редуктором и редуктор в порядке, но просто хочу, чтобы мое описание было более понятным.
Действия Redux
export const startMatching = (userid, userprofile, usergender, genderpreference) => (dispatch) => {
dispatch({ type: MATCHING_REQUEST });
......
dispatch(matchingConversation(userspool[number].id, doc.data(), userprofile, {time: "", from: "", content: ""}, number, userspool));
}
export const matchingConversation = (user2id, user2profile, user1profile, message, number, userspool) => (dispatch, getState) => {
.....
.then(() => {
dispatch({ type: CHAT_SUCCESS, payload: doc.id });
})
.then(() => {
dispatch({ type: MATCHING_SUCCESS, payload: user2id });
})
}
Редуктор
const initialState = {
loading: false,
chatid: "",
buddy: "",
}
const authReducer = (state = initialState, action) => {
const {type, payload} = action;
switch(type) {
......
case CHAT_SUCCESS:
return {
...state,
chatid: action.payload
}
case MATCHING_REQUEST:
return {
...state,
loading: true
}
case MATCHING_SUCCESS:
return {
...state,
buddy: action.payload,
loading: false
}
case MATCHING_FAIL:
return {
...state,
buddy: action.payload,
loading: false
}
default: return state;
}
}