Я не могу обновить состояние своего компонента.. Кто-нибудь понимает, как это исправить?

#reactjs #wordpress

#reactjs #wordpress

Вопрос:

Я не могу понять, почему моя функция renderMovies () не хочет обновлять состояние моего компонента.данные, и я не могу отобразить компонент на моем экране ?! Все идет нормально, пока renderMovies не заработает.. Я думаю, что this.setState(newState) в моей функции fetchPostData работает неправильно… Кто-нибудь знает, как это исправить? Я пробовал разные способы, но не могу решить эту проблему.

 
class Movies extends React.Component {
    constructor(props) {
        super(props)
        this.state = { data: {}}

        this.fetchPostData = this.fetchPostData.bind(this)
        this.renderMovies = this.renderMovies.bind(this)
        this.populatePageAfterFetch = this.populatePageAfterFetch.bind(this)

    }

    componentDidMount() {
        this.fetchPostData()
    }

    fetchPostData() {
        fetch(`http://localhost/reacttest/wp-json/wp/v2/movies?per_page=100`)
            .then(response => response.json())
            .then(myJSON => {
                let objLength = Object.keys(myJSON).length
                let newState = this.state;

                for (let i = 0; i < objLength; i  ) {
                    let objKey = Object.values(myJSON)[i].title.rendered;
                    // console.log(objKey)
                    let currentMovie = newState.data[objKey];


                    currentMovie = {};
                    currentMovie.name = Object.values(myJSON)[i].title.rendered;

                    currentMovie.description = Object.values(myJSON)[i].content.rendered;

                    currentMovie.featured_image = Object.values(myJSON)[i]['featured_image_url'];

                    currentMovie.genre = Object.values(myJSON)[i]['genre'];

                }

                this.setState(newState)
            })
    }

    renderMovies() {
        if(this.state.data) {
            const moviesArray = Object.values(this.state.data)
            console.log(moviesArray)
            return Object.values(moviesArray).map((movie, index) => this.populatePageAfterFetch(movie, index))
        }
    }

    populatePageAfterFetch(movie, index) {
        if (this.state.data) {

            return (
                <div key={index} index={index}>
                    <h2>{movie.title}</h2>
                    <h3>{movie.genre}</h3>
                    <p>{movie.description}</p>
                </div>
            )
        }
    }

    render() {
        return (
            <div>
                <h1>Movies</h1>
                <div>{this.renderMovies()}</div>
            </div>
        )
    }
}

  

Когда я пытаюсь console.log (moviesArray), он показывает мне:

введите описание изображения здесь

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

1. получаете ли вы значения, если регистрируете ‘newState’ непосредственно перед строкой ‘this.setState (newState)’?

Ответ №1:

Проблема

Вы сохраняете текущее состояние в переменной с именем newState , никогда не обновляете ее, а затем сохраняете ту же ссылку на объект обратно в состояние. Состояние реакции никогда не обновляется.

 let newState = this.state;

for (let i = 0; i < objLength; i  ) {
  ...
}

this.setState(newState);
  

Кроме того, вы изменяете состояние

 let currentMovie = newState.data[objKey];
currentMovie = {};
  

Но это тоже не работает, поскольку начальное состояние является пустым объектом, поэтому newState.data[objKey] всегда не определено. (так что на самом деле ничего не меняется)

Решение

Похоже, что вы намеревались сопоставить myJSON данные / значения с объектами movie для обновления this.state.data . Могу ли я предложить это решение. Ключ в том, чтобы всегда создавать новые ссылки на объекты для любого объекта, который вы обновляете.

 fetchPostData() {
  fetch(`http://localhost/reacttest/wp-json/wp/v2/movies?per_page=100`)
    .then(response => response.json())
    .then(myJSON => {
      this.setState(prevState => ({
        // array::reduce over the JSON values
        data: Object.values(myJSON).reduce((movies, movie) => {
          // compute movie key
          const name = movie.title.rendered;

          return {
            ...movies,
            [name]: {
              ...movies[name], // copy any existing movie properties
              // merge in new/updated properties
              name,
              description: movie.content.rendered,
              featured_image: movie.featured_image_url,
              genre: movie.genre,
            },
          }
        }, { ...prevState.data }) // use previous state as initial value for reduce
      }))
    })
}