How can I re render a component? REACT-NATIVE - javascript

im new in react native, and im doing a note block, the problem now its that once i click save, it saves it to the array but when i get back to home screen, where i show the notes that are saved it doesnt show the last one, until i re load the entire project, how can I do to re render it? i have seen that i have to use this.forceUpdate(), but it doesnt working either, heres the code:
this is the home screen, the first screen the user will see, it shows the notes that are saved calling the component Notes
render() {
return (
<>
<View style = {this.styles.container}>
<View>
<Text style = {this.styles.Text}>Welcome to home!</Text>
</View>
<Notes></Notes>
<View style = {this.styles.View}>
<Button title = "Create new note" styles = {this.styles.Button} onPress = {() => this.props.navigation.navigate("Create_note")}></Button>
</View>
<View style = {this.styles.View}>
<Button title = "Notes" styles = {this.styles.Button} onPress = {() =>this.props.navigation.navigate("See_notes")}></Button>
</View>
</View>
</>
);
}
heres the component Notes:
class Notes extends Component {
constructor(props) {
super(props);
this.state = {
array_notes: [],
}
}
componentDidMount() {
this.fetch_notes();
}
fetch_notes = async() => {
try {
const data = await AsyncStorage.getItem("array_notes");
if (data != null) {
const array_notes = JSON.parse(data);
this.setState({array_notes: array_notes});
}else {
console.log("with no data");
}
}catch (error) {
console.log(error);
}
}
render() {
return (
<>
<View style = {this.styles.View}>
<FlatList data = {this.state.array_notes} renderItem = {({item}) => (<Text style = {this.styles.Text}>{item.title}</Text>)} keyExtractor = {(item) => item.title}></FlatList>
</View>
</>
);
}
and heres the create a new note screen, where the user type a new note:
class Create_note extends Component {
constructor() {
super();
this.state = {
title: "",
content: "",
}
}
save_Data = async() => {
try {
const array_notes = await AsyncStorage.getItem("array_notes");
if (array_notes === null) {
const array_notes = [];
await AsyncStorage.setItem("array_notes", JSON.stringify(array_notes));
}else {
const new_note = {'title': this.state.title, 'content': this.state.content};
const array_notes = JSON.parse(await AsyncStorage.getItem("array_notes"));
array_notes.push(new_note);
await AsyncStorage.setItem("array_notes", JSON.stringify(array_notes));
}
}catch(error) {
console.log(error);
}
}
}
render() {
return (
<>
<Text style = {this.styles.Text }>Welcome to Shum Note!</Text>
<View>
<TextInput style = {this.styles.TextInput_title} placeholder = "Title" multiline = {true} maxLength = {80} onChangeText = {(title) => this.setState({title: title})}></TextInput>
<TextInput style = {this.styles.TextInput_content} placeholder = "Content" multiline = {true} onChangeText = {(content) => this.setState({content: content})}></TextInput>
<Button title = "Save" onPress = {this.save_Data}></Button>
</View>
<View style = {this.styles.back_Button}>
<Button title = "Go back home" onPress = {() => this.props.navigation.navigate("Home")}></Button>
</View>
</>
);
}
once i saved the new note and press the go back home it doesnt show the last one until like i said, i reload the entire project, but something curious, is if i go to create_note screen it will re render each time, but it doesnt happend with home, why?

You have to pass in fetch_notes as a prop in Create_note.
this.props.navigation.navigate("Create_note", fetch_notes: this.fetch_notes)
In your Create_note get the function from navigation.
const { fetch_notes} = this.props.route.params; //https://reactnavigation.org/docs/params/
After saving the note you have to call it like this: this.props.fetch_notes()

You can add the.props.navigation.addListener. When you are back from next screen to previous screen API calling because of addListener focus on current screen and UI is render because of state changes.
componentDidMount() {
this.focusListener =
this.props.navigation.addListener("didFocus", () => {
this.fetch_notes()
});
}

Related

React native, ImageBackground check image has loaded before navigating to page

Is there a way I can check if the image has loaded before navigating to a page?
My image if loaded from a url then displayed to the background, I get random errors saying ImageBackground is undefined.
Redux shows the image existing in the store, but I still get the error when navigating to the page:
export const RescueMeLandingScreen = (props) => {
const { navigation } = props;
const {
rescueMe: {
rescueMeSplashScreen: {
backgroundImage: { url }, //https://xxx/v3/assets/bltba214d69f78d0dfb/blt90b1f745b5b348ef/62333622893506175b30a63f/xxx.png
buttonText,
informationText,
title: pageTitle,
},
},
} = useSelector((state) => state);
...
return (
<>
<RACPageStructure loading={false} title={pageTitle} isMain>
<ScrollView contentContainerStyle={styles.scollView}>
<ImageBackground source={{ uri: url }} style={styles.imageBackground}>
...
</ImageBackground>
</ScrollView>
</RACPageStructure>
</>
);
};
You could try conditionally rendering the component.
Example:
{ url !== undefined && <ImageBackground>}
If that doesn't work, you could also create a custom component wrapper for your component that would return a default image if the other one is undefined.
Example:
const ImageBackgroundWrapper = () => {
if (url === undefined) {
return ();
} else {
return ();
}
}

React Native Calendar - Agenda not updating even when state updates

Agenda doesn't update even when new data are added. Only when the app is reloaded it updates.
Here is my code:
const CalendarScreen = () => {
const list = useSelector((state) => state.getTodo.list);
const [items, setItems] = useState({});
const loadItems = () => {
list.forEach((data) => {
const strTime = data.createdDate;
if (!items[strTime]) {
items[strTime] = [];
list.forEach((datalist) => {
items[strTime].push({
name: datalist.title,
});
});
}
});
const newItems = {};
Object.keys(items).forEach((key) => {
newItems[key] = items[key];
});
setItems(newItems);
};
const renderItem = (item) => {
return (
<View >
<Text>{item.name}</Text>
</View>
);
};
return (
<View style={flex: 1}>
<Agenda
items={items}
loadItemsForMonth={loadItems}
renderItem={renderItem}
pastScrollRange={1}
futureScrollRange={1}
/>
</View>
);
};
export { CalendarScreen };
Expectation: Just want the Agenda to update automatically when new data is added in the state instead of having to reload the app.
It looks like that refresh depends call of loadItemsForMonth.
Unfortunately I cannot see when Agenda call loadItemsForMonth

How to hide top bar after 3 seconds in React Native

I have been trying to achieve hiding (or slide up) my react native startup app top bar after 3 seconds, then have a button to press to show the top bar, but could not. I've searched online how to do it, but have not seen good solution for it. Please I need help here, the below is snippet code of what I tried doing but it did not work.
<HeaderHomeComponent /> is the top header I created and imported it in my Home screen
const Home = () => {
const camera = useRef();
const [isRecording, setIsRecording] = useState(false);
const [flashMode, setFlashMode] = useState(RNCamera.Constants.FlashMode.off);
const [cameraType, setCameraType] = useState(RNCamera.Constants.Type.front);
const [showHeader, setShowHeader] = useState(true);
const onRecord = async () => {
if (isRecording) {
camera.current.stopRecording();
} else {
setTimeout(() => setIsRecording && camera.current.stopRecording(), 23*1000);
const data = await camera.current.recordAsync();
}
};
setTimeout(()=> setShowHeader(false),3000);
const DisplayHeader = () => {
if(showHeader == true) {
return <HeaderHomeComponent />
} else {
return null;
}
}
// useEffect(() => {
// DisplayHeader();
// }, [])
return (
<View style={styles.container}>
<RNCamera
ref={camera}
type={cameraType}
flashMode={flashMode}
onRecordingStart={() => setIsRecording(true)}
onRecordingEnd={() => setIsRecording(false)}
style={styles.preview}
/>
<TouchableOpacity
style={styles.showHeaderButton}
onPress={() => {
setShowHeader(!showHeader);
}}>
<Button title='Show' />
</TouchableOpacity>
<HeaderHomeComponent />
You were really close.
This is how it should be done:
useEffect(() => {
setTimeout(toggleHeader,3000);
}, []);
const toggleHeader = () => setShowHeader(prev => !prev);
Then inside the "return":
{showHeader && <HeaderHomeComponent />}
As simple as that.
This should help you get started in the right direction, you can use animation based on your preference to this code.
import React, {useState, useEffect} from 'react';
import { Text, View, StyleSheet, Button } from 'react-native';
import Constants from 'expo-constants';
export default function App()
{
const [showStatusbar, setShowStatusbar] = useState(true)
useEffect(() =>
{
setTimeout(() =>
{
setShowStatusbar(false)
}, 3000)
}, [])
return (
<View style={styles.container}>
{
showStatusbar
? <View style = {styles.statusBar}>
<Text>Status Bar</Text>
</View>
: null
}
<Button title = "Show Status bar" onPress = {() => setShowStatusbar(true)}/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#ecf0f1',
},
statusBar:
{
height: 50,
backgroundColor:'lightblue',
justifyContent:'center',
alignItems:'center'
}
});
Instead of setTimeout use Animation.
or
Check this lib : https://www.npmjs.com/package/react-native-animated-hide-view
or
check below answers which might help you
Hide and Show View With Animation in React Native v0.46.

I need help fixing the Bug in my list array

I code community I have a bug in my search bar. The app is very easy... Ever time a user creates a name it displays in a list array. My problem is that when the user creates a name that name is not displaying my the list but when I search the name, it does show the list.
Here the video so you can have a better understanding
https://www.youtube.com/watch?v=WIM-H4xXqMw
and the code. I need help in my search bar and display the list when clicking the button
FolderHome.js - component
const [folder, emptyFolder] = useState([]);
const data = folder;
const [searchTerm, setSearchTerm] = useState("");
let [filteredData, setFilteredData] = useState(data);
//this function is when the user press the button we want to use the folderName(value) and display in a list.
//then when we add a foldername we update and add a new folder name.
//To understand I am just adding a folder name into my empty array. Now my array as a Folder inside.
const addFolder = (folderName) => {
emptyFolder((currentFolder) => [
...currentFolder,
{ id: Math.random().toString(), value: folderName },
]);
};
//Search
const _searchFilterFunction = (event, data) => {
let newData = [];
setSearchTerm({ searchTerm: event });
if (event) {
newData = data.filter((item) => {
const textData = event.toUpperCase();
const nameFolder = item.value.toUpperCase();
return nameFolder.includes(textData);
});
setFilteredData([...newData]);
} else {
setFilteredData([...data]);
}
};
return (
<View style={styles.HomeContainer}>
<TextInput
underlineColorAndroid="transparent"
autoCapitalize="none"
placeholderTextColor="#9a73ef"
style={styles.search}
placeholder="Search"
onChangeText={(value) => {
_searchFilterFunction(value, data);
}}
/>
<FolderInput myFolder={addFolder} />
{filteredData.map((item, index) => {
return <Text key={item.id}>{item.value}</Text>;
})}
</View>
);
};
FolderInput.js - Component
const FolderInput = (props) => {
//This function we handle the input and output off Folder
const [outputFolder, inputFolder] = useState("");
//This arrow function is handling the folder name on onChangeText in TextInput
const folderName = (entereName) => {
inputFolder(entereName);
};
//Function to clear input when done enter folder name
const clearInput = () => {
props.myFolder(outputFolder);
inputFolder("");
};
return (
// TouchableWithoutFeedback allow to register a touche withou nothing happen to it
<View style={styles.outputContainer}>
<TouchableWithoutFeedback
onPress={() => {
Keyboard.dismiss();
}}
>
<View style={styles.containerFolder}>
<TextInput
blurOnSubmit
placeholder="Create Folder"
style={styles.containerTextInput}
onChangeText={folderName}
//we pass the name folder into is value by biding and store into outputFolder
value={outputFolder}
/>
<TouchableOpacity>
<AntDesign
onPress={clearInput}
name="addfolder"
backgroundColor="black"
size={30}
/>
</TouchableOpacity>
</View>
</TouchableWithoutFeedback>
</View>
);
};
export default FolderInput;
Thank you so much for all hard work your in advance
:)
You should not have filteredData as state. it is a computed result of searchTerm and folder.
just declare it as:
const filteredDate = folder.filter((item) => {
const textData = searchTerm.toUpperCase();
const nameFolder = item.value.toUpperCase();
return nameFolder.includes(textData);
});
You can take a look at a simple implementation of search in this snack:
https://codesandbox.io/s/cocky-cori-n704s?file=/src/App.js

How to save an array of Items in AsyncStorage React Native?

What i want to make is a bookmark list, but i don't know how i can save an array of items in AsyncStorage, my skills are basic on react.
I just need the function to save posts (post image, title and id) when i press the button "Save to bookmark".
export default class PostDetails extends Component {
constructor(props) {
super(props);
const {params} = props.navigation.state;
this.state = {
item: params.item
};
}
render() {
const {item} = this.state;
return (
<Image source={{uri: item.post_image}}/>
<Text> {item.post_id} </Text>
<Text> {item.post_title} </Text>
<Button>
<Text> Save to Bookmark </Text>
</Button>
);
}
}
I think you want to use JSON.stringify(arrayToSave); see the docs for JSON.stringify(). It will convert the array to a JSON string that can be saved to AsyncStorage and then can be retrieved at a later stage.
const saveBookmarks = async (bookmarksArray) => {
try {
const bookmarksString = JSON.stringify(bookmarksArray);
await AsyncStorage.setItem('#MyStore:bookmarks',bookmarksString);
} catch (error) {
// Error saving data
}
};
<Button onClick={() => saveBookmarks(yourArray)} />
To retrieve it you can use const theSavedArray = JSON.parse(stringFromAsyncStorage); the docs for JSON.parse()
try {
const bookmarksString = await AsyncStorage.getItem('#MyStore:bookmarks');
if (bookmarksString !== null){
// We have data!!
const bookmarksArray = JSON.parse(bookmarksString);
}
} catch (error) {
// Error retrieving data
}

Categories