Изменение реквизита, являющегося объектом, не обнаруживается компонентом

#javascript #reactjs

Вопрос:

Я передаю этот объект в качестве опоры компоненту под названием LoungeItem :

 lounge = {guests: [], _id: "60ec3840306969479c25b822", name: "Lounge_name"}
 

подобный этому:

 <LoungeItem lounge={lounge} />
 

Если я добавлю гостя в lounge.guests so, это будет выглядеть так:

 lounge = {guests: [
      {_id: "60e5892d1e8b3c2c24c5463c", name: "username", surname: "usersurname", profile: {…}}
    ], _id: "60ec3840306969479c25b822", name: "Lounge_name"}
 

Это изменение не обнаруживается внутри LoungeItem и componentWillReceiveProps не срабатывает:

Это компонент:

 class LoungeItem extends Component {
  componentWillReceiveProps(nextProps) {
    console.log(
      "🚀 ~ file: LoungeItem.js ~ line 18 ~ LoungeItem ~ componentWillReceiveProps ~ nextProps",
      nextProps
    );
  }

  render() {
    const { lounge } = this.props;
    console.log("===================INSIDE LOUNGE ITEM =================");
    console.log(
      "🚀 ~ file: PublicLoungeList.js ~ line 7 ~ PublicLoungeList ~ render ~ lounge",
      lounge
    );
    console.log("===================INSIDE LOUNGE ITEM =================");
    const guests = lounge.guests;
    console.log(
      "🚀 ~ file: LoungeItem.js ~ line 33 ~ LoungeItem ~ render ~ guests",
      guests
    );

    return <div>Lounge</div>;
  }
}
 

ПРАВКА 1: Как и было запрошено, вот как lounge изменяется в редукторе:

 case JOIN_LOUNGE:
  const newLounges = state.lounges.map((lounge) => {
    if (lounge._id == action.payload.lounge_id) {
      lounge.guests.push({
        _id: action.payload._id,
        name: action.payload.name,
        surname: action.payload.surname,
        profile: {
          _id: action.payload.profile._id,
          handle: action.payload.profile.handle,
        },
      });
      return lounge;
    } else {
      return lounge;
    }
  });
 

И для получения более подробной информации это обрабатывается следующим образом по LoungesList компонентам:

 class LoungesList extends Component {
  render() {
    const { lounges } = this.props;
    console.log(
      "===================INSIDE PUBLIC LOUNGE LIST================="
    );
    console.log(
      "🚀 ~ file: PublicLoungeList.js ~ line 7 ~ PublicLoungeList ~ render ~ lounges",
      lounges
    );
    console.log(
      "===================INSIDE PUBLIC LOUNGE LIST================="
    );

    return lounges.map((lounge) => {
      console.log(
        "🚀 ~ file: PublicLoungeList.js ~ line 19 ~ PublicLoungeList ~ returnlounges.map ~ lounge",
        lounge
      );
      return <LoungeItem lounge={lounge} />;
    });
  }
}
 

И этот называется здесь:

 class Home extends Component {
  render() {
    return <PublicLoungeList lounges={this.props.lounges}></PublicLoungeList>;
  }
}

const mapStateToProps = (state) => ({
  lounges: state.chats.lounges,
});
 

Комментарии:

1. Как здесь задействован Redux? Я не вижу ничего связанного.

2. Изменение гостей осуществляется с помощью redux. Но я не добавил его сюда, потому что не имеет значения, было ли изменение сделано с помощью redux или самим родительским компонентом.

3. Это может зависеть от того, как вы изменяете свойство, например, если вы изменяете свойство «на месте» lounge , это будет один и тот же объект, и может не вызвать обновление.

4. Согласованный. Вам нужно убедиться, что вы lounge заменяете новый объект (например, используя Object.assign ), а не модифицированную версию в том же месте (например, с помощью назначения на месте). Если вы хотите, чтобы мы помогли, вы должны показать нам код, который обновляется lounge .

5. Я просто толкаю гостя в гостиную.гостей. Если это не считается «изменением реквизита», как мне обновить lounge таким образом, чтобы изменения были обнаружены.

Ответ №1:

Вы не должны мутировать lounge.guests , вместо этого используйте оператор распространения для создания новой гостиной с обновленным массивом

 case JOIN_LOUNGE:
  const newLounges = state.lounges.map((lounge) => {
    if (lounge._id == action.payload.lounge_id) {
     return {
       ...lounge,
       guests: [...lounge.guests,{
        _id: action.payload._id,
        name: action.payload.name,
        surname: action.payload.surname,
        profile: {
          _id: action.payload.profile._id,
          handle: action.payload.profile.handle,
        },
      }]
     }
    } else {
      return lounge;
    }
  });