如何让 componentDidMount 再次渲染?

How can I make componentDidMount render again?

我正在 Explore 组件中获取 api(makeup API) 并在 Explorebutton 中使用它。 我将品牌作为 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>
        )
    }

}

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

注意:你并不是真的需要state中的API URL,将item放在state上,并以此为基础构造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>
    );
  }
}

How can I make componentDidMount render again?

不确定您的意思,但我认为您要问的是 How can I make componentDidMount *run* again?,为此,您需要在 callbackFunction 到 运行 中使用相同的代码又是那个componentDidMount 只会在组件第一次渲染后 运行。

另请注意,如果您想重新呈现 FlatList,您需要传递 extraData,以便它知道它需要重新呈现。