How to generate random words from an API? - react-native

I wrote this code :
export default class WordGenerator extends React.Component {
state = {
wordToShow : [test],
}
componentDidMount(){
this.changeWordToShow()
}
changeWordToShow=()=>{
fetch('https://random-word-api.herokuapp.com/word?lang=it').then(response=>this.setState({wordToShow: response}))
}
render(){
return (
<View style={Styles.container}>
<Text style={Styles.paragraph}>
{this.state.wordToShow[0]}
</Text>
<Button title="Change word" onPress={()=>this.changeWordToShow()}/>
</View>
);
}
}
When I click myself on the link https://random-word-api.herokuapp.com/word?lang=it, I get an array containing one random italian word. However, when I press the button, the value of wordToShow seems to become null, as 'test' disappear with no italian words to replace it ...

The response is in application/json, so it needs to be decoded first. Something like this:
changeWordToShow = () => {
fetch('https://random-word-api.herokuapp.com/word?lang=it')
.then((response) => response.json())
.then((response) => this.setState({ wordToShow: response }));
};

Related

react native share image url

there are two part of codes, the first : a page with list of touchable image and the second: with onPress the image open in new page in full size.
till now every thing is fin. but in new page when I want to share image url, it doesn't work!!!
here is some part of my code:
part one:
const Images = [
{ url: require("../Images/dress.jpg") },
{ url: require("../Images/111.jpg") },
{ url: require("../Images/222.jpg") },
...
]
export class Dress extends Component {
render() {
return (
...
<View>
{Images.map((image, index) => (
<TouchableOpacity
key={index}
onPress={() => this.props.navigation.navigate("ShowImage", {url:image.url})}
>
<Image source={image.url}/>
</TouchableOpacity>
))}
</View>...
part two (above onPress direct to new page)
export class ShowImage extends Component {
shareMessage = async (PhotoLink) => {
console.log('myUrl'+PhotoLink)
const result = await Share.share({
title: "title goes here",
message: ("hi"+PhotoLink),
});
render() {
return (
...
<TouchableOpacity
onPress={()=>this.shareMessage(this.props.route.params.url)}
>
...
when I use local image the result is: "hi3" or "hi4" or ...
when I use web image from internet the result is: "hi[object Object]"
I don't know where is the problem!! plz help me :)
Edit your Part1 code like this:
const Images = [
{ url: "../Images/dress.jpg" },
{ url: "../Images/111.jpg" },
{ url: "../Images/222.jpg" },
]
export class Dress extends Component {
render() {
return (
<View>
{Images.map((image, index) => (
<TouchableOpacity
key={index}
onPress={() => this.props.navigation.navigate("ShowImage", {url:image.url})}>
<Image source={require(image.url)}/>
</TouchableOpacity>
))}
</View>
)
}
}
and Part2 like this:
export class ShowImage extends Component {
shareMessage = async (PhotoLink) => {
console.log('myUrl'+PhotoLink)
const result = await Share.share({
title: "title goes here",
message: ("hi"+PhotoLink),
});
render() {
return (
...
<TouchableOpacity
onPress={()=>this.shareMessage(this.props.route.params.url)}
>
...
and try again. when you require an image it is converted to an object.
and if you want to use web image url, you can simply edit Part1 like this:
const Images = [
{ url: "https://en.wikipedia.org/wiki/File:Image_created_with_a_mobile_phone.png" },
]
export class Dress extends Component {
render() {
return (
<View>
{Images.map((image, index) => (
<TouchableOpacity
key={index}
onPress={() => this.props.navigation.navigate("ShowImage", {url:image.url})}>
<Image source={{uri: image.url}}/>
</TouchableOpacity>
))}
</View>
)
}
}

onChangeText setState only sets one character not the whole string

I accept text input from a search bar and setState to text but its only one character at a time how can I continue to update and add to the state rather than replace what's in state? I feel like this is the intended action but my code does not do this.
class FindRecipesScreen extends Component {
static navigationOptions = {
title: "Find Recipes",
header: null
};
constructor(props) {
super(props);
this.state = {
search: "",
recipe: "",
text: "",
};
}
backToHomePage = () => {
this.props.navigation.navigate("Home");
};
componentDidMount() {
this.props.getRecipeList(this.props.auth.jwt);
}
handleSearch = text => {
console.log("text", text);
this.setState({text: text});
};
render() {
return (
<View style={styles.recipe}>
<View style={styles.recipeBar}>
<ActionNavbar title="Find Recipes"
leftAction={this.backToHomePage}
leftIcon={require("app/assets/icons/cancel.png")}
rightAction={this.backToHomePage}
rightIcon={require("app/assets/icons/filter.png")}/>
</View>
<View>
<View>
<SearchBar
containerStyle={styles.searchContainer}
inputContainerStyle={styles.searchInputContainer}
inputStyle={styles.searchInput}
lightTheme
searchIcon={searchIcon}
round
onChangeText={this.handleSearch}
placeholder="Search Cookbooks"
/>
<View style={styles.forward}>
<Image
style={styles.forwardIcon}
width={18}
height={18}
source={require("app/assets/icons/forward.png")}
/>
</View>
</View>
</View>
</View>
);
}
}
I found the solution... I needed const { search } = this.state; after render but before return with searcher
Use debouncer in the handleSearch function so the state is set after your debounce time.

How to access child component values from the parent in react native?

I have a login screen with following structure:
import Logo from '../components/Logo'
import Form from '../components/Form';
export default class Login extends React. Component {
<View style={styles.container} >
<Logo/>
<Form type="login"/>
<View style={styles.signUpTextCont}>
...
</View>
</View>
and here is my Form component:
export default class Form extends React.Component {
constructor (props){
super(props)
this.state = {
username : '',
password : ''
}
}
handleChangeUsername = (text) => {
this.setState({ username: text })
}
handleChangePassword = (text) => {
this.setState({ password: text })
}
render() {
return (
<View style={styles.container} >
<TextInput
ref={(input) => { this.username = input }}
onChangeText = {this.handleChangeUsername}
value = {this.state.username}
/>
<TextInput
ref={(input) => { this.password = input }}
onChangeText = {this.handleChangePassword}
value = {this.state.password}
/>
<TouchableOpacity style={styles.button}>
<Text style={styles.buttonText}>{this.props.type}</Text>
</TouchableOpacity>
</View>
);
}
}
now I would like to have a checkLogin() method in Login screen (parent).
How can I access username and password values to check them in the Login screen?
I will be grateful if someone could help.
Try using ref keyword for accessing the child values.
<View style={styles.container} >
<Logo/>
<Form type="login"
ref={'login'}/>
<View style={styles.signUpTextCont}>
...
</View>
</View>
To Acess Child Component Values in parent:
onClick = () =>{
//you can access properties on child component by following style:
let userName = this.refs['login'].state.username;
let password = this.refs['login'].state.password;
}
you can use callback to send username and password to parent like this sample code:
Form:
handleChangeUsername = (text) => {
this.setState({ username: text })
this.props.userChange(text)
}
handleChangePassword = (text) => {
this.setState({ password: text })
this.props.passChange(text)
}
login:
add two state named user and pass and:
setUser = (text) => {
this.setState({user:text})
}
setPass = (text) => {
this.setState({pass:text})
}
checkLogin = () => {
// check user and pass state...
}
<Form
type="login"
userChange = {(text) => { this.setUser(text) } }
passChange = {(text) => { this.setPass(text) } }
/>
and now, user and pass is in state in login and you can check it.
I hope this can help you

View inside curly braces not showing

I'm new in ReactNative. I'm following a tutorial from Udemy. I've been trying to show a value from a variable. its working in the instructor's video but not in my code. the code is given below:
export default class App extends React.Component {
state = {
placeName: '',
places: []
}
placeNameChangedHandler = val => {
this.setState({
placeName: val
})
}
placeSubmitHandler = () => {
if (this.state.placeName.trim() === "") {
return;
}
this.setState(prevState => {
return {
places: prevState.places.concat(prevState.placeName)
}
})
}
render() {
const placesOutput = this.state.places.map(place => {
<Text>{place}</Text>
})
return (
<View style={styles.container}>
<View style={styles.inputContainer}>
<TextInput
placeholder="Type something"
style={styles.placeInput}
value={this.state.placeName}
onChangeText={this.placeNameChangedHandler}/>
<Button
style={styles.placeButton}
onPress={this.placeSubmitHandler}
title="Add"/>
</View>
<View>
{this.placesOutput}
</View>
</View>
);
}
}
but the {placeOutput} is not showing anything. its working in the instructor's video but not in my code. What am I doing wrong?
You aren't returning anything in your map() function. Your render function should look like this:
render() {
const placesOutput = this.state.places.map(place => {
return <Text>{place}</Text> //Added return statement
})
return (
<View style={styles.container}>
<View style={styles.inputContainer}>
<TextInput
placeholder="Type something"
style={styles.placeInput}
value={this.state.placeName}
onChangeText={this.placeNameChangedHandler}/>
<Button
style={styles.placeButton}
onPress={this.placeSubmitHandler}
title="Add"/>
</View>
<View>
{this.placesOutput}
</View>
</View>
);
}
All I did was add a return statement in your this.state.places.map() function.

React Native: Fetch data every 10 clicks on a button

I've just started working with React Native a few days ago and I find myself a bit stuck. I want to display the values one by one from an api with the click of a button. However, how can I do this without fetching the data every single time, but rather every 10 clicks or so? The code I have right now doesn't work the way I want it to and I do understand why - the countData() function is always called anew, therefore the variable i is always stuck at zero and never advances forward. Ideally, I'd like to loop through the first set of values, display them one by one as the button is clicked and then fetch new data (from the same api) after it runs out of values.
export default class ComponentOne extends Component {
constructor(props) {
super(props);
this.state = {
questions: '',
questions2: '',
}
}
fetchData() {
if (this.state.questions == '') {
fetch('my url')
.then((response) => response.json())
.then((responseData) => {
this.setState({
questions: responseData,
});
this.countData();
})
.done();
}
else this.countData();
}
countData() {
for (let i=0; i < this.state.questions.length; i++) {
this.setState({
questions2: this.state.questions[i],
});
}
}
render() {
return (
<View style={styles.container}>
<View style={styles.textStyle}>
<Text style={styles.instructions}>
Welcome! Click the button to generate a question.
</Text>
<TouchableHighlight
onPress={() => this.fetchData()}
style={styles.bigButton}
underlayColor="lightskyblue">
<Text style={styles.bigButtonText}>Hit me</Text>
</TouchableHighlight>
<Text style={styles.question}>{this.state.questions2}</Text>
</View>
</View>
);
}
}
I hope the problem is clear, thanks in advance!
First things first: you should consider not giving you apis url like that.
I didn't test the code in an app but it should work
export default class ComponentOne extends Component {
constructor(props) {
super(props);
this.state = {
questions: [],
question: "",
count: 0,
}
}
componentWillMount() {
this.fetchData();
}
fetchData() {
fetch('YOUR_URL')
.then((response) => response.JSON())
.then((responseJSON) => {
this.setState({questions: responseJSON, count: 0})
})
}
newQuestion() {
if (this.state.questions[count] != null) {
this.setState({
question: this.state.questions[this.state.count],
count: this.state.count + 1,
})
}
else { //make the fetch call once all of your questions has been displayed
this.fetchData();
}
}
render() {
return (
<View style={styles.container}>
<TouchableHighlight onPress={() => this.newQuestion()}>
<Text>Hit me</Text>
</TouchableHighlight>
<Text>{this.state.question}</Text>
</View>
</View>
);
}
}