Replace Text Component with TextInput Component - React Native - reactjs

I want to display the fill in the blanks type component in the application.
For Example: Hi, my name is _______. Some more fill in _______ blanks.
I've a response something like this: {text: Hi, my name is insert_input. Some more fill in insert_input blanks.}
<Text>{item.text}<TextInput/></Text>
I'm little bit of confused, how we can achieve that.

This should be sufficient. Here is the working code
split the sentence based on the string and add them back to back by keeping text input in between them. Don't add it for the last item.
import * as React from 'react';
import { Text, View, StyleSheet, TextInput } from 'react-native';
import Constants from 'expo-constants';
// You can import from local files
import AssetExample from './components/AssetExample';
// or any pure javascript modules available in npm
import { Card } from 'react-native-paper';
export default function App() {
const string =
"Hi, my name is insert_input. Some more fill in insert_input blanks.";
const splitString = string.split("insert_input");
const modifiedString = () => {
var newStr = "";
splitString.map((subStr, i) => {
newStr = <Text>
<Text>{newStr}</Text>
<Text>{subStr}</Text>
{splitString.length - 1 === i ? null : <TextInput placeholder="________________________"/>}
</Text>;
});
console.log(newStr);
return newStr;
};
return (
<View style={styles.container}>
<Text style={styles.paragraph}>
{modifiedString()}
</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
paragraph: {
margin: 24,
fontSize: 18,
fontWeight: 'bold',
textAlign: 'center',
},
});

Related

Error relating to props and renderItem in react native flatlist

im making a simple hello world type project in react native to familiarize myself with everything before I move onto my first project.
The goal of this one was to display an array with a flatlist, but the kicker was I was going to slowly modularize it (ie. array is stored somewhere else, flatlist uses renderitem, renderitem is a seperate component, ect.)
import React, {useState} from 'react';
import {StyleSheet, Text, View, FlatList} from 'react-native';
function App () {
const [orders, setOrders] = useState([
{ customer: 'Clair' , age: 45, item: 'Corn', key: 0},
{ customer: 'Alex' , age: 39, item: 'Tomato', key: 1},
]);
const renderer = ({order}) =>
{
const customerName = order.customer;
const itemName = order.item;
return(
<Text>I am {customerName} and I would like a {itemName} please</Text>
);
};
return(
<View style={styles.container}>
<FlatList
data={orders}
renderItem={renderer}
keyExtractor={(order) => order.key}
/>
<Text> Hello World!!!! </Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
orderContainer:
{
borderColor: 'black',
borderWidth: 5,
padding: 20,
alignItems: 'center',
},
listText:
{
justifyContent: 'center',
alignItems: 'center',
}
});
export default App;
the first dummy mistake ive learned is that you shouldnt declare a "component" (in this case the renderer) inside the main return statement for the app
now I just need to wrap my head around the prop handling. The error specifically has to do with the renderItem line. apparently the prop, which from my understanding should be one of the orders from the useState array, doesnt exist
any help is appreciated :)
The object renderer get is as follows.
item: Object
index : 0
separators: Object
Thus to get the customer details you need to update your function to follow.
const renderer = ({item}) =>
{
const customerName = item.customer;
const itemName = item.item;
return(
<Text>I am {customerName} and I would like a {itemName} please</Text>
);
};

Using dropdown component in react-navigation throws error when handler is called

I'm trying to use react-navigation with react-native-dropdown in order to have a dropdown in the header to change what is rendered in the view below.
Whenever I try to execute the handler, react-native-dropdown I get the error "undefined is not a function (near'...this.props.data.map')when react-native-dropdown attempts to render again and maps the dropdown using (this.props.data.map((rows, index) => etc.
Below is the code I'm using:
import React, {Component} from "react"
import {Dimensions, ScrollView, StyleSheet, width, View, TouchableOpacity} from "react-native"
import {Images} from "../../theme"
import DropdownMenu from 'react-native-dropdown-menu';
import Pdf from 'react-native-pdf';
import { Header } from "react-native/Libraries/NewAppScreen";
import { connect } from 'react-redux';
import { NavigationActions } from 'react-navigation';
import { drop } from "lodash";
class InformationScreen extends Component {
constructor(props) {
super(props)
var informationScreens = props.global.appConfig.information_screens
var informationScreenTitles = Object.keys(informationScreens)
state = {
informationScreens: informationScreens,
selectedDropdown: informationScreens[0]
}
}
static navigationOptions = ({ navigation }) => {
return {
headerTitle: <DropdownMenu
style={{flex: 1}}
bgColor={'clear'}
tintColor={'#666666'}
activityTintColor={'rgba(2, 122, 255, 1.0)'}
// arrowImg={}
// checkImage={}
// optionTextStyle={{color: '#333333'}}
// titleStyle={{color: '#333333'}}
// maxHeight={300}
handler={(selection, row) => navigation.setParams({'headerTitle': navigation.state.params[selection][row]})}
data={navigation.state.params}
/>
};
};
render() {
return (
<View style={styles.container}>
<Pdf
source={{ uri: "https://someurl.com/dl/sites/default/files/page/2020%20BYU%20Football%20Almanac_3.pdf", cache: true}}
onLoadComplete={(numberOfPages,filePath)=>{
console.log(`number of pages: ${numberOfPages}`);
}}
style={styles.pdf}
/>
</View>
)
}
}
const styles = StyleSheet.create({
image: {
flex: 1,
},
container: {
flex: 1,
justifyContent: 'flex-start',
alignItems: 'center',
marginTop: 25,
},
pdf: {
flex:1,
width:Dimensions.get('window').width,
height:Dimensions.get('window').height,
}
})
function mapStateToProps(state) {
const global = state.get('global');
return { global };
}
export default connect(mapStateToProps)(InformationScreen);
Ray you were absolutely correct, I figured it out about 5 minutes before you posted.
navigation.state.params was valid and the dropdown would populate, however when I would try to setParams, it would change the format of params to a JSON object instead of an array.
This was remedied by putting my array one JSON object deeper so the object still contained the array after setParams was called. I then called that object in the data.
data={navigation.state.params.informationScreens}
Thank you so much for your help, I'll start using StackOverflow more often.
I suspect this.props.data is either not provided or not an array, so this.props.data.map is undefined, and attempting to invoke it will get you an 'undefined is not a function' error. Is navigation.state.params an array?
If you pass data={navigation.state.params || []} does the issue go away?

React native require with backticks

I'm implementing an app and on the homescreen I have a flatlist element with inside for each item a card element.
import React, { useEffect, useContext } from 'react';
import { Text, View, StyleSheet, FlatList } from 'react-native';
import {ListItem, Card} from 'react-native-elements';
import { Context as ParkingContext } from '../context/ParkingContext';
const HomeScreen = () => {
const { state: {records}, fetchParkings } = useContext(ParkingContext);
useEffect(() => {
fetchParkings();
},[])
return (
<View style={styles.container}>
<FlatList
data={records}
keyExtractor={item => item.recordid}
renderItem={({item}) => {
return (
<Card containerStyle={styles.cardStyle} title={item.fields.description}>
<Text style={styles.textStyle}>{item.fields.address.replace(/\n/g,'')}</Text>
<Text style={styles.textStyle}>Aantal vrije plaatsen: {item.fields.availablecapacity}</Text>
</Card>
)
}}
/>
</View>
)
};
const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: 25
},
cardStyle: {
padding: 0,
borderRadius: 10
},
textStyle: {
flexDirection: 'row',
flex: 1,
marginBottom: 10,
marginLeft: 5
}
});
export default HomeScreen;
The card element has a property image which can be used to set a image to the card. I want to give different images to the cards by doing
image={require(`../../assets/${item.fields.description}.jpg`)}
but require doesn't let me do this with backticks and neither with a variable... is there some way to use backticks or a variable so I can have different photo's for the different cards?
My apologies if the answer is obvious but I tried a lot of things and it does not work.
Assuming you created your react app with create-react-app or you are using webpack to bundle your code then what you are trying to achieve will not work: Since Webpack is running in build-time, it can't figure out which modules to bundle when the name is a dynamic variable. Packaging happens once before runtime so those variables don't have values yet.
If you have a small number of images, you can do something like this:
let image1 = require('../../assets/xxx.jpg');
let image2 = require('../../assets/xxx.jpg');
...
image={image1}
...
But of course, if you have a long list of images this way will not be optimal
Further details can be found in the discussion of this issue

when i use const { myCardStyle } = this.myStyles; at the class below it shows error

I'm learning react native. in my application, for one of the components, when i use this. at const { myCardStyle } = this.myStyles; at the class below it shows error: Possible unhandled Promise Rejection ..., but when i put it without this it works.
const Card = (myProps) => {
const { myCardStyle } = myStyles;
console.log(8 + myProps.children);
return(
<View style={myCardStyle}>
{myProps.children}
</View>
);
};
const myStyles = {
myCardStyle: {
blabla
}
};
const can be accessed without the help of this keyword. Look at the example below. styles can be accessed globally by the class without using this keyword.
this keyword is used when we want to access state or prop objects that are binded to the class. Normally u can bind the finctions using bind keyword
/**
* Sample React Native App
* https://github.com/facebook/react-native
* #flow
*/
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';
export default class VideoExample extends Component {
__click(){
//if u want to access this keyword here
//u have to bind this function
}
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to React Native!
</Text>
<Text onPresss={this._click.bind(this)}/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
});
AppRegistry.registerComponent('VideoExample', () => VideoExample);
Try to move const myStyle inside Card method and before
const { myCardStyle } = myStyles
const Card = (myProps) => {
const myStyles = {
myCardStyle: {
blabla
}
};
const { myCardStyle } = myStyles;
console.log(8 + myProps.children);
return(
<View style={myCardStyle}>
{myProps.children}
</View>
);
};
styles are defined outside the class VideoExample so you can't access it using the this.myStyles.
You can directly refer the variable by it's name and if you want to access it in another class you can access it by VideoExample.myStyles.

Merge / Combine two or more different StyleSheet components in React Native?

I'm separating my styles in the following way:
styles /
|-- base.js
|-- base.ios.js
|-- base.android.js
Each of them exports a StyleSheet component created as in this example:
import { StyleSheet } from 'react-native';
export default StyleSheet.create({
statusBar: {
height: 20
});
How can I merge them so I only have one base style object? I'm looking for something like:
const baseStyles = mergeStyles(baseStyle, platformStyle);
you are very close:
const baseStyles = [baseStyle, platformStyle];
basically any component can cascade styles like this:
<View style={[styles.style1,styles.style2]}></View>
You can also use StyleSheet.flatten method. See documentation here.
var styles = StyleSheet.create({
listItem: {
flex: 1,
fontSize: 16,
color: 'white',
},
selectedListItem: {
color: 'green',
},
});
StyleSheet.flatten([styles.listItem, styles.selectedListItem]);
// returns { flex: 1, fontSize: 16, color: 'green' }
UPDATE:
StyleSheet.flatten internally uses StyleSheetRegistry.getStyleByID(style) to resolve style objects represented by IDs. IDs enable optimizations through the bridge and memory in general. Referring to style objects directly will deprive you of these optimizations.
So flatten method is better than style={ [ styles.listItem, styles.selectedListItem ] }
You can combine style sheets using the spread operator '...', be warned that any variables of the same name will be overwritten by the last instance.
Heres a small demo app to demonstrate:
'use strict';
import React, { Component } from 'react';
import {
Alert,
Button,
StyleSheet,
Text,
AppRegistry,
View,
} from 'react-native';
class listTest extends Component {
render() {
return (
<View style={styles3.myViewBox}>
<Text style = {styles3.myTextBox1}>
TEST
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
myTextBox1: {
backgroundColor:'red',
},
myViewBox: {
backgroundColor:'blue',
margin:15,
padding:15,
}
});
const styles2 = StyleSheet.create({
myTextBox2: {
backgroundColor:'yellow',
},
myViewBox: {
backgroundColor:'green',
margin:15,
padding:15,
},
});
const styles3 = {...styles,...styles2};
AppRegistry.registerComponent('listTest', () => listTest);
EDIT:
If you're running ES5 you can just use:
const styles3 = Object.assign(styles,styles2);
Now ReactNative lets you combine two styles using a more functional approach. Use the function StyleSheet.compose so you can do the following as per documentation:
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
const App = () => (
<View style={container}>
<Text style={text}>React Native</Text>
</View>
);
const page = StyleSheet.create({
container: {
flex: 1,
padding: 24,
backgroundColor: '#fff',
},
text: {
fontSize: 30,
color: '#000'
},
});
const lists = StyleSheet.create({
listContainer: {
flex: 1,
backgroundColor: '#61dafb',
},
listItem: {
fontStyle: 'italic',
fontWeight: 'bold'
},
});
const container = StyleSheet.compose(page.container, lists.listContainer); // if you wanna compose more than one style just use a map.reduce function and compose two at the time until you have consumed you list of styles
const text = StyleSheet.compose(page.text, lists.listItem);
export default App;

Resources