Quantcast
Channel: Active questions tagged react-native+ios - Stack Overflow
Viewing all articles
Browse latest Browse all 16750

Can’t update the property of a child component from a parent component in React Native

$
0
0

I’m newbie to React Native for mobile development. I’m using Expo. I can’t manage a state.

I have a SearchTextBox component, I want to set text property from the parent component, however I couldn’t manage it using useState.

import React, { useState, useEffect } from "react";import { TouchableOpacity } from "react-native-gesture-handler";import { Ionicons } from "@expo/vector-icons";import { StyleSheet, TextInput, View } from "react-native";import defaultStyles from "../config/styles";function SearchTextBox({  searchQuery,  width = "100%",  onSearch,  ...otherProps}) {  const [query, setQuery] = useState(searchQuery);  const [isClearable, setIsClearable] = useState(    query != null && query.length > 0  );  const onChange = (e) => {    const { text } = e.nativeEvent;    setQuery(text);    const length = text.length;    setIsClearable(length > 0);    if (length >= 2 && onSearch) onSearch(text);  };  const onClear = () => {    setQuery("");    setIsClearable(false);  };  return (<View style={styles.container}><View        style={{          width: 72,        }}><Ionicons          name="md-search"          size={32}          color={defaultStyles.colors.medium}          style={styles.icon}        /></View><View        style={{          flex: 2,        }}><TextInput          autoCorrect={false}          autoFocus={false}          autoCapitalize="none"          placeholder="Search"          placeholderTextColor={defaultStyles.colors.medium}          style={[defaultStyles.text, styles.text]}          onChange={onChange}          value={query}          {...otherProps}        /></View>      {isClearable && (<View><TouchableOpacity onPress={onClear}><Ionicons              name="md-close"              size={32}              color={defaultStyles.colors.medium}              style={styles.icon}            /></TouchableOpacity></View>      )}</View>  );}const styles = StyleSheet.create({  container: {    backgroundColor: defaultStyles.colors.light,    borderRadius: 24,    flexDirection: "row",    flex: 1,    marginVertical: 10,  },  icon: {    margin: 15,    paddingRight: 15,  },  text: {    flexGrow: 1,    fontSize: 18,  },});export default SearchTextBox;

And I use like this:

import React, { useState, useEffect, useRef } from "react";import { View, StyleSheet, FlatList, AsyncStorage } from "react-native";import { AdMobBanner } from "expo-ads-admob";import * as Device from "expo-device";import { ListItem, ListItemSeparator } from "../components/lists/";import Screen from "../components/Screen";import SearchTextBox from "../components/SearchTextBox";import AnimatedTextList from "../components/AnimatedTextList";import colors from "../config/colors";import searchApi from "../api/search";import useApi from "../hooks/useApi";import ads from "../config/ads";function HomeScreen() {  const search = useApi(searchApi.search);  const [data, setData] = useState([]);  const [showRandomWords, setShowRandomWords] = useState(true);  const [randomWords, setRandomWords] = useState([]);  const [bannerType, setBannerType] = useState("banner");  const [initialQuery, setInitialQuery] = useState();  const getDeviceTypeAsync = async () => {    const deviceType = await Device.getDeviceTypeAsync();    setBannerType(      deviceType === Device.DeviceType.TABLET ? "fullBanner" : "banner"    );  };  useEffect(() => {    getDeviceTypeAsync;  }, []);  const onSearch = async (value) => {    setShowRandomWords(value == null || value == undefined || value === "");    const result = await search.request(value);    if (!result.ok) return;    setData(result.data.data);  };  useEffect(() => {    const getRandomWords = async () => {      try {        const result = await AsyncStorage.getItem("random_words");        if (!result) return;        setRandomWords(JSON.parse(result));        setShowRandomWords(true);      } catch (error) {        console.log(error);      }    };    getRandomWords();  }, []);  const bannerError = (error) => {    console.log("An error occured while trying to show AdMob", error);  };  const onRandomWordPress = (item) => {    setInitialQuery(item.title);    onSearch(initialQuery);  };  return (<Screen><View style={styles.searchBox}><SearchTextBox          searchQuery={initialQuery}          width="90%"          onSearch={onSearch}        /></View>      {showRandomWords && (<View><AnimatedTextList items={randomWords} onPress={onRandomWordPress} /></View>      )}<View style={styles.result}><FlatList          data={data}          keyExtractor={(word) => word.id.toString()}          renderItem={({ item }) => (<ListItem title={item.word} subTitle={item.descp} />          )}          ItemSeparatorComponent={ListItemSeparator}        /></View><View style={styles.bottomBanner}><AdMobBanner          style={styles.bottomBanner}          bannerSize={bannerType}          adUnitID={ads.unitID}          servePersonalizedAds          didFailToReceiveAdWithError={bannerError}        /></View></Screen>  );}const styles = StyleSheet.create({  bottomBanner: {    alignContent: "center",    alignItems: "center",    alignSelf: "center",    bottom: 0,    position: "absolute",    width: "100%",  },  container: {    flex: 1,    alignItems: "center",    width: "100%",    flexDirection: "column",  },  searchBox: {    backgroundColor: colors.white,    height: 100,    width: "100%",    padding: 10,  },  result: {    width: "100%",    flex: 1,  },});export default HomeScreen;

Here’s I bind the property

<SearchTextBox          searchQuery={initialQuery}          width="90%"          onSearch={onSearch}        />

In onRandomWordPress I set the variable but however it doesn’t update the input’s text.

const onRandomWordPress = (item) => {    setInitialQuery(item.title);    onSearch(initialQuery);  };

What’s the proper way to do this or what’s wrong with my implementation?

Thanks!


Viewing all articles
Browse latest Browse all 16750

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>