2017-02-13 2 views
1

Я пытаюсь обновить дочерний элемент на основе родительского состояния.React - Обновление ребенка

В родителю:

<ImageGallery id={this.state.id} images={this.state.images} /> 

В детстве:

render(){ 
    console.log("Rendering.............. gallery "); 
    console.log(this.props.images); 
    var images = this.props.images.map(function(image, i){ 
     return (
     <Image key={image.id} source={image.source} style={{width: 400, height: 400}}></Image> 
    ); 
    }); 

    console.log("Array of images to render: => "); 
    console.log(images); 
    return (
     <View>{images}</View> 
    ); 
    } 

Но рендер только раз, потому что исходное состояние является пустым, то данные извлекаются на компоненте родителя сделал крепление ,

EDIT Отвечая на вопросы

как обновить состояние родительского компонента, и как вы планируете обновить> ребенок? - havenchyk

Потому что государство в настоящее время ссылаются на ребенка:

//Here 
images={this.state.images} 

EDIT 2

Это мой компонент сделал крепление:

1- Запрос список объектов изображений 2- затем получение этих изображений как blob 3- с помощью base64, чтобы отобразить изображение 4- создания объекта источника для отображения на который будет использоваться на ребенка 5- меняющегося состояния

async componentDidMount() { 
    try{ 
     let response = await API.get(`communities/${this.state.id}/community-pictures`); 

     let json = await response.json(); 

     if (!response.ok) { 
     throw json; 
     } 

     let images = json.data; 
     let newImages = []; 

     images.forEach(async (image) => { 
     let response = await API.request_blob(`communities/${this.state.id}/community-pictures/${image.id}/view`); 
     let data = await response.base64(); 

     let type = response.respInfo.headers['Content-Type']; 
     let imageUri = `data:${type};base64,` + data; 

     let source = {uri: imageUri, scale: 1}; 

     newImages.push(Object.assign(image, {source: source})); 
     }); 

     this.setState({ 
     images: newImages 
     }); 

     console.log("Changing images!!"); 
     console.log(this.state); 

    } catch (json) { 
     // Surppressing this error 
    } 
    } 

И вы можете извлечь ребенка визуализации. Он использует this.props.images для установки экрана. Но не работает. Родитель изменяет свои состояния и ребенок не обновляется.

EDIT SUPER WIERD Ребята, я заметил что-то очень странное. Я добавил console.log на componentDidMount, чтобы увидеть новое состояние. Проверьте, что хром печатает:

enter image description here

Но, когда я открыть объект, чтобы увидеть массив, проверить его:

enter image description here

WOW !! Что такое хапеннин ?!

+0

как обновить состояние родительского компонента, и как вы ожидаете, чтобы обновить ребенка? – havenchyk

+0

Вы устанавливаете состояние в родительском после получения данных в componentDidMount()? Это вызовет другой рендер. –

+1

вы можете показать код, в котором вы извлекаете данные? –

ответ

1

Проблема в том, что images.forEach(async (image) => { выполняется как асинхронный.

Поэтому, когда React собирается проверить, должен ли он отображаться или нет, он сравнивает пустой массив и ничего не делает.

Затем эти асинхронные вызовы завершены, и по мере изменения содержимого той же ссылки newImages, ваш console.log изменится.

Раствор для удаления асинхронной Foreach, вы могли бы поставить все внутри функции асинхронной и вызывать так:

let images = json.data; 
let newImages = []; 

for (int index = 0; index < images.length; images++) { 
    let img = await fetch(images[index]); 
    newImages.push(img); 
} 
+1

Да, вот и все! Ничего не случилось с моей реализацией Parent/Child в React. Выполняя то, что вы сказали сейчас, состояние изменяется правильно, а также ребенок.PS: не нужно переопределять SCU! –

2

После того, как вы изменили состояние компонента через setState(state), вы вызываете rerender текущего компонента, поскольку реализация по умолчанию метода shouldComponentUpdate возвращает true, если состояние компонента не равно следующему состоянию. Вы можете узнать больше об этом here.

Итак, ваш компонент обновлен, и был вызван метод render(). Затем выполните следующие действия: shouldComponentUpdate дочерних элементов.

Существует пример того, как реагировать на элементы рендеринга. Should component update scheme

Там vDOMEq указывает, были ли предоставленные элементы Реактива эквивалентными или нет. There - это документация.

Поэтому, когда вы обновляете реквизиты дочернего компонента SCU, возвращается false, поэтому повторное воспроизведение не требуется. Как это можно избежать? Просто реализуйте SCU самостоятельно.

shouldComponentUpdate(nextProps, nextState) { 
    nextProps.propToChange !== this.props.propToChange 
} 

Помните не мутировать свой реквизит, потому что если вы - равно проверка вернет ложь (потому что ссылки имеют то же самое), и вы получите неожиданные ошибки.

+0

Итак, если реализация по умолчанию всегда истинна при изменении состояния. Итак, лучший способ - правильно изменить состояние ребенка? Но как я могу это сделать, если я получаю реквизиты только на конструкторе? Или как я могу поделиться государством, не создавая компонент высокого порядка (таким образом, они будут совместно использовать одно и то же состояние). –

+0

. Лучший способ реализации (изменение дочернего элемента зависит от родителя) - передать состояние родителя через реквизита и реализовать «SCU» самостоятельно, чтобы изменить элемент, когда реквизиты изменены, но если вы получаете реквизиты только в конструкторе (это действительно странно, почему? как бы вы обновили свое состояние) - установить состояние зависит от реквизита в конструкторе 'this. state = {...} '. –

+0

У моего класса есть только конструктор, получающий реквизит и функцию рендеринга. Я буду использовать ** shouldComponentUpdate **. И посмотрите, работает ли это. –

Смежные вопросы