如何使componentDidMount再次呈现?

时间:2019-12-24 12:44:06

标签: reactjs react-native state react-props

我要在“浏览”组件中获取api(makeup API)并在“浏览”按钮中也使用它。 我将品牌作为ExploreButtons中的按钮。当我在ExploreButtons中的FlatList元素中单击按钮时,我想在ExploreButtons中的第二个FlatList中查看来自api的图像。单击按钮时,componentDidMount是否可以重新渲染?

import React, { Component } from 'react'
import { View } from 'react-native'
import ExploreButtons from './ExploreButtons'

export default class Explore extends Component {
    constructor(props) {
        super(props);
        this.state = {
            isLoading: true,
            makeupApi: 'http://makeup-api.herokuapp.com/api/v1/products.json',
        }
    }
    callbackFunction = (item) => {
        this.setState({
            makeupApi: 'http://makeup-api.herokuapp.com/api/v1/products.json?brand=' + item,
        })
    }

    async componentDidMount() {
        try {
            const response = await fetch(this.state.makeupApi);
            const responseJson = await response.json();
            this.setState({
                isLoading: false,
                dataSource: responseJson,
            }, function () {
            });
            const reformattedArray = this.state.dataSource.map(obj => {
                var rObj = {};
                rObj = obj.brand;
                return rObj;
            });
            this.setState({
                duplicatesRemoved: reformattedArray.filter((item, index) => reformattedArray.indexOf(item) === index)
            })
        }
        catch (error) {
            console.error(error);
        }
    };

    render() {
        console.log(this.state.makeupApi)
        return (
            <View style={{ flex: 1 }}>
                <ExploreButtons
                    api={this.state.dataSource}
                    removedDuplicatesFromAPI={this.state.duplicatesRemoved}
                    parentCallback={this.callbackFunction}
                    makeupApi= {this.state.makeupApi} />
            </View>
        )
    }

}


export default class ExploreButtons extends Component {

    getBrandImages = (item) => {
        this.props.parentCallback(item)
    }

    render() {
        return (
            <View style={{ flex: 1 }}>
                <View>
                    <FlatList
                        horizontal
                        showsHorizontalScrollIndicator={false}
                        data={this.props.removedDuplicatesFromAPI}
                        renderItem={({ item }) =>
                            <TouchableOpacity
                                style={styles.exploreButtons}
                                onPress={() => {
                                    this.getBrandImages(item)
                                }}
                            >
                                <Text>{item}</Text>
                            </TouchableOpacity>
                        }
                        keyExtractor={item => item}
                    />
                </View>
                <View>
                    <FlatList
                        data={this.props.api}
                        renderItem={({ item }) =>
                            <View>
                                <Image source={{ uri: item.image_link }}
                                    style={{
                                        alignSelf: "center",
                                        width: '100%',
                                        height: 300,
                                    }} />
                            </View>
                        }
                        keyExtractor={item => item.id.toString()} />
                </View>
            </View>
        )
    }

}

2 个答案:

答案 0 :(得分:2)

您可以将所有逻辑放在componentDidMount中的另一个函数中,并在调用回调时调用它。作为第一种非常粗略的方法,它将起作用:

注意:您实际上不需要状态中的API URL,只需将项目放在状态中并根据其构造URL。

import React, { Component } from 'react';
import { View } from 'react-native';
import ExploreButtons from './ExploreButtons';

export default class Explore extends Component {
  API_URL = 'http://makeup-api.herokuapp.com/api/v1/products.json';

  constructor(props) {
    super(props);
    this.state = {
      isLoading: true,
      item: null,
      dataSource: null,
      duplicatesRemoved: [],
    };
  }

  getAPIURL(item) {
    if(!item){
      return API_URL
    }
    return `${API_URL}?brand=${item}`;
  }

  async fetchData(item) {
    try {
      const url = getAPIURL(item);
      const response = await fetch(url);
      const responseJson = await response.json();

      this.setState({
        isLoading: false,
        dataSource: responseJson,
        item,
      });

      const reformattedArray = responseJSON.map(({ brand }) => brand);

      this.setState({
        duplicatesRemoved: reformattedArray.filter(
          (item, index) => reformattedArray.indexOf(item) === index,
        ),
      });
    } catch (error) {
      console.error(error);
    }
  }

  async componentDidMount() {
    fetchData();
  }

  render() {
    const { dataSource, duplicatesRemoved, item } = this.state;
    return (
      <View style={{ flex: 1 }}>
        <ExploreButtons
          api={dataSource}
          removedDuplicatesFromAPI={duplicatesRemoved}
          parentCallback={this.fetchData}
          makeupApi={getURL(item)}
        />
      </View>
    );
  }
}

export default class ExploreButtons extends Component {
  getBrandImages = item => {
    this.props.parentCallback(item);
  };

  render() {
    const { removedDuplicatesFromAPI, api } = this.props;

    return (
      <View style={{ flex: 1 }}>
        <View>
          <FlatList
            horizontal
            showsHorizontalScrollIndicator={false}
            data={removedDuplicatesFromAPI}
            renderItem={({ item }) => (
              <TouchableOpacity
                style={styles.exploreButtons}
                onPress={() => {
                  this.getBrandImages(item);
                }}
              >
                <Text>{item}</Text>
              </TouchableOpacity>
            )}
            keyExtractor={item => item}
          />
        </View>
        <View>
          <FlatList
            data={api}
            renderItem={({ item }) => (
              <View>
                <Image
                  source={{ uri: item.image_link }}
                  style={{
                    alignSelf: 'center',
                    width: '100%',
                    height: 300,
                  }}
                />
              </View>
            )}
            keyExtractor={item => item.id.toString()}
          />
        </View>
      </View>
    );
  }
}

答案 1 :(得分:0)

  

如何使componentDidMount再次呈现?

不确定您的意思,但是我想您要问的是How can I make componentDidMount *run* again?,为此,您需要在callbackFunction中具有相同的代码才能再次运行它。 componentDidMount仅在组件首次渲染后运行。

还要注意,如果要重新渲染FlatList,则需要传递extraData,以便知道它需要重新渲染。