Я получаю профиль пользователя по ID. Но когда я пытаюсь зайти на страницу другого пользователя по ссылке с той же страницы, я не могу поймать новый ID из URL. Он ловится в методе componentWillReceiveProps, но я не могу вызвать из него запрос к базе данных для получения данных по ID, потому что возникает бесконечный цикл.
Как мне получить новый ID по ссылке /profile/5cc6c0e743d02ff2860d8f20, чтобы компонент обновился и я смог получить данные из базы данных и вставить их в компонент?
на самом деле мне нужно получить реквизиты из props.match.params.id и передать их в this.props.getUserById (this.props.match.params.id), в то время как props.match.params.id доступен только в метод componentWillReceiveProps
class ProfileUser extends Component {
state = {
user: {}
};
componentDidMount() {
// When first time i load component it works fine, i call database and get info
this.props.getUserById(this.props.match.params.id);
}
componentWillReceiveProps(nextProps) {
// Here I get user information
this.setState({user: nextProps.profile.user})
// when I switch to another page with another ID this.props.match.params.id, this method works but I can't call this.props.getUserById(this.props.match.params.id); from here because an infinite loop appears
// this.props.getUserById(this.props.match.params.id);
}
render() {
console.info(this.state.user)
return (<div></div>)
}





1- установить идентификатор как переменную состояния 2- в компоненте будет получена проверка реквизитов, если nextProps.match.params.id совпадает с идентификатором, который мы установили на шаге 1, если да, не делайте сетевой вызов, иначе снова установите идентификатор и сделайте сетевой вызов
Сравните, старые и новые свойства получают пользователя только тогда, когда компонент делает что-либо с новый реквизит
componentWillReceiveProps(nextProps) {
if (nextProps.match.params.id !== this.props.match.params.id ) {
this.props.getUserById(this.props.match.params.id);
}
Перезагружайте пользователя только при изменении идентификатора:
if (nextProps.match.params.id !== this.props.match.params.id) {
this.props.getUserById(nextProps.props.match.params.id);
}
Причина получения бесконечного цикла
Вы получаете бесконечный цикл, потому что componentWillReceiveProps вызывается всякий раз, когда изменяется реквизит, поэтому при такой функции, если вы напишете эту строку this.props.getUserById(this.props.match.params.id), она извлечет информацию старого пользователя (скажем, пользователя A), потому что this.props относится к старым реквизитам, а nextProps относится к новым (давайте скажем, пользователь B), следовательно, вы снова пользователь A. В этот момент nextProps ссылается на пользователя A, а this.props ссылается на пользователя B. Итак, props меняется, он снова выбирает пользователя B, и вы получаете бесконечный цикл .
Решение
Извлекать пользователя только в том случае, если оба идентификатора разные и пользователь nextProps.props.match.params.id вместо this.props.
if (nextProps.match.params.id !== this.props.match.params.id) {
this.props.getUserById(nextProps.props.match.params.id);
}
Улучшения
Я рекомендовал вам использовать хуки вместо компонентов на основе классов для всех новых компонентов, которые вы создаете. Это делает вещи более простыми. См. документацию для хука useEffect, вы упомянете в нем аргументы, которые извлекают пользователя только в том случае, если что-то от пользователя изменяется. так что только одна вещь будет делать работу для componentDidMount и ComponentWillReceiveProps
Вы будете использовать компонент ProfileUser следующим образом:
< ProfileUser
{...props}
/>
передайте ID и KEY в этом компоненте, как это
< ProfileUser
key = {this.props.match.params.id}
id = {this.props.match.params.id}
{...props}
/>
всякий раз, когда меняется ключ, компонент будет повторно отображаться. Итак, он запустится из конструктора, и у вас будет каждый раз новый ID в пропсах.
роутер будет выглядеть так
<Route
exact
path = "/something/:id"
render = {(props)=> (
<ProfileUser
key = {props.match.params.id}
id = {props.match.params.id}
{...props}
/>
)}
/>
для получения дополнительной информации об этом -- перейдите по этой ссылке - https://dev.to/ganderzz/react-controlling-rendering-through-keys-274m