调用多个函数进行渲染

时间:2017-11-01 17:17:15

标签: javascript reactjs

首先,我想解释一下我想做什么以及我的问题出在哪里。

最初我做一个获取请求来加载一些数据,因为这里工作正常。 在使用这个数据的一个值后,我想再做一次获取。为此,我调用另一个函数 renderImage(),在那里我进行获取,然后渲染我想要的代码。

我的问题是没有渲染任何内容,因为没有将状态更改为已加载。当然,fetch是异步的,需要更多时间。 而且我不知道它是如何运作的,而且更简单,因为我认为我这样做有点复杂。

这是我的代码:

class Dashboard extends Component{

constructor(props){
    super(props)
    this.state = {
      dataSource: new ListView.DataSource({
        rowHasChanged: (row1, row2) => row1 !== row2
      }),
      loaded: false,
       datos: '',
    }
}

componentDidMount(){
    this.fetchData();
}

    fetchData(){
        fetch(REQUEST_URL)
        .then((response) => response.json())
        .then ((responseData) =>{
            this.setState({
                dataSource: this.state.dataSource.cloneWithRows(responseData),
            })      
        })
    }

    renderLoadingView(){
        return(
            <View>
            <Text>Cargando...</Text>
            </View>
            )
    }

    async renderImage(receta){
            const REQUEST_URL = "yyyyyyyy" + receta.user_id;
            const response = await fetch(REQUEST_URL);
            const json = await response.json();
            this.setState({ loaded : true});    
            return(       
                    <Card >
                        <CardItem>
                            <Left>
                            <TouchableOpacity>
                            <Thumbnail style={{width: 50, height: 50, borderRadius: 25}} source={{uri: json.imageUrl}} />     
                            </TouchableOpacity>
                                <Body>
                                    <Text>{receta.Titulo}</Text>
                                    <Text>{receta.Username}</Text>
                                </Body>
                            </Left>
                        </CardItem>
                   </Card>             
            )           
    }


    renderReceta(receta){
            return this.renderImage(receta);                
    }

    render(){       
        if(!this.state.loaded){
            return this.renderLoadingView();
        }
        else{
            return(
            <Container>
                <ListView 
                dataSource={this.state.dataSource}
                renderRow={this.renderReceta.bind(this)}
                />
                </Container>
                )
        }

    }

}

1 个答案:

答案 0 :(得分:0)

也许不是“答案”,但问题有点模糊。这可以通过多种方式解决。

选项一: 首先加载数组,然后显示列表,并异步“sideload”每行的图像。 如果你有很多图像可能会很糟糕,所以要小心。你也可以在这里加载你可能永远不会渲染的图像(它们不在视图中,例如用户永远不会滚动到它们),但你也不会加载它们两次......优点和缺点。

class Dashboard extends Component{

    constructor(props){
        super(props)
        this.state = {
            dataSource: new ListView.DataSource({
                rowHasChanged: (row1, row2) => row1 !== row2
            }),
            loaded: false,
            datos: '',
            images: {

            }
        }
    }

    componentDidMount(){
        this.fetchData();
    }

    fetchData(){
        fetch(REQUEST_URL)
            .then((response) => response.json())
            .then ((responseData) =>{
                this.setState({
                    loaded: true,
                    dataSource: this.state.dataSource.cloneWithRows(responseData),
                });
                this.fetchImageUrls(responseData);
            });
    }

    fetchImageUrls(responseData){ //assuming respons data is an array of receta objects
        responseData.forEach(({user_id})=>{
            fetch("wwwsomewhere").then(r => r.json()).then(({imageUrl})=>{
                this.setState({
                    images: Object.assign(this.state.images, {
                        [user_id]: imageUrl
                    })
                });
            });
        });
    }

    renderLoadingView(){
        return(
            <View>
                <Text>Cargando...</Text>
            </View>
        )
    }

    renderImage(receta){
        const {Titulo, Username, user_id} = receta;
        return(
            <Card >
                <CardItem>
                    <Left>
                        <TouchableOpacity>
                            {this.state.images[user_id] ?
                                <Thumbnail style={{width: 50, height: 50, borderRadius: 25}} source={{uri: this.state.images[user_id]}} />
                                : "Loading (load thumb here?)"
                            }
                        </TouchableOpacity>
                        <Body>
                        <Text>{receta.Titulo}</Text>
                        <Text>{receta.Username}</Text>
                        </Body>
                    </Left>
                </CardItem>
            </Card>
        )
    }


    renderReceta(receta){
        return this.renderImage(receta);
    }

    render(){
        if(!this.state.loaded){
            return this.renderLoadingView();
        }
        else{
            return(
                <Container>
                    <ListView
                        dataSource={this.state.dataSource}
                        renderRow={this.renderReceta.bind(this)}
                    />
                </Container>
            )
        }
    }
}

选项2: 将所有加载捆绑到一个并解决后重新渲染。

class Dashboard extends Component{

    constructor(props){
        super(props)
        this.state = {
            dataSource: new ListView.DataSource({
                rowHasChanged: (row1, row2) => row1 !== row2
            }),
            loaded: false,
            datos: '',
            recetas: {

            }
        }
    }

    componentDidMount(){
        this.fetchData();
    }

    fetchData(){
        fetch(REQUEST_URL)
            .then((response) => response.json())
            .then ((responseData) =>{
                this.setState({
                    dataSource: this.state.dataSource.cloneWithRows(responseData),
                });
                this.fetchImageUrls(responseData);
            });
    }

    fetchImageUrls(responseData){ //assuming respons data is an array of receta objects
        //Load all images
        Promise.all(responseData.map(({user_id})=>{
            return fetch("wwwsomewhere").then(r => r.json());
        })).then((recetasArray)=>{
            //When all thumb objects (Recetas) have been resolved
            //map over the receta object array and create a hash (so you can access them by id later)
            this.setState({
                loaded: true,
                recetas: recetasArray.reduce((acc, receta)=>{
                    acc[recept.user_id] = receta;
                    return acc;
                },{})
            });
        });
    }

    renderLoadingView(){
        return(
            <View>
                <Text>Cargando...</Text>
            </View>
        )
    }

    renderImage(receta){
        const {Titulo, Username, user_id} = receta;
        return(
            <Card >
                <CardItem>
                    <Left>
                        <TouchableOpacity>
                            <Thumbnail style={{width: 50, height: 50, borderRadius: 25}} source={{uri: this.state.recetas[user_id]}} />
                        </TouchableOpacity>
                        <Body>
                        <Text>{receta.Titulo}</Text>
                        <Text>{receta.Username}</Text>
                        </Body>
                    </Left>
                </CardItem>
            </Card>
        )
    }


    renderReceta(receta){
        return this.renderImage(receta);
    }

    render(){
        if(!this.state.loaded){
            return this.renderLoadingView();
        }
        else{
            return(
                <Container>
                    <ListView
                        dataSource={this.state.dataSource}
                        renderRow={this.renderReceta.bind(this)}
                    />
                </Container>
            )
        }
    }
}

未经测试的代码,但只是想分享我的想法。