Невозможно правильно изменить состояние в componentDidMount - PullRequest
2 голосов
/ 07 февраля 2020

Я работаю над своим проектом, используя firebase. Код такой, как показано ниже.


var storage = firebase.storage()
var storageRef = storage.ref();

export default class WallPics extends Component {
    constructor(props){
        super(props)
        this.state={
            images : []
        }
    }
    componentWillMount(){
        var imgArr=[]
        storageRef.listAll()
            .then(allPics=>{
                allPics.items.forEach(function (picRef){
                   picRef.getDownloadURL()
                    .then(function (url){
                        imgArr.push(
                            <img src={url} alt="pics" />
                        )
                    })

                })
                this.setState({
                    images : imgArr
                })  
            })
    }

    render() {
        return (
            <div>
                {this.state.images}
            </div>
        )
    }
}

. В приведенном выше коде я получаю все ссылки на картинки из своего хранилища firebase и добавляю URL-адреса для загрузки картинок. к imgArr. После добавления всех URL-адресов к imgArr я хочу изменить состояние. Но здесь this.setState становится пустым imgArr. Но я хочу изменить значение состояния на imgArr с URL-адресами для загрузки изображений . Как я могу сделать это сейчас?

Ответы [ 2 ]

2 голосов
/ 07 февраля 2020

Я не предлагаю вам переводить компонент непосредственно в состояние, согласно официальным документам React здесь :

Состояние должно содержать данные, которые могут изменить обработчики событий компонента для запуска обновления пользовательского интерфейса.

Также четко указано, что компоненты не должны go в состоянии:

this.state должно содержать только минимальный объем данных, необходимый для представления состояния вашего пользовательского интерфейса. Таким образом, он не должен содержать:

Реагировать на компоненты : построить их в render () на основе базовых параметров и состояния.

Таким образом, я предлагаю вам сначала извлечь извлечение действия в отдельную функцию для лучшего чтения и установить URL-адреса, которые нужно указать вместо компонента.

fetchPics = async() => {
  const allPics = await storageRef.listAll();
  const allUrls = await allPics.items.map(picRef => picRef.getDownloadURL());
  // here I use async, you might also use promise.all() 
  // as stated in @Alexandr Zavalii's answer
  this.setState({ images : allUrls })
}

componentDidMount() {
  this.fetchPics();
}

Наконец, визуализируйте компоненты с URL-адресами в функции рендеринга.

render() {
  return (
    <div>
      {this.state.images.map(url => <img src={url} alt="pics" />)}
    </div>
  )
}
2 голосов
/ 07 февраля 2020

getDownloadURL является асинхронным? если да, то вам следует дождаться обещания разрешить

Попробуйте что-то вроде этого?

async componentDidMount() {
   let imgArr=[]
   let allPics = await storageRef.listAll()
   let promises = []
   allPics.items.forEach((picRef) => {
       promises.push(picRef.getDownloadURL())
   })

   const urls = await Promise.all(promises);

   for(let url of urls){
      imgArr.push(<img src={url} alt="pics" />)
   }

   this.setState({images : imgArr})  
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...