I am trying to return two things, a separate Mission component and a flat list. When I run my emulator, I can get the return on the Mission component but not the flat list. There are no errors, so I'm a bit lost with how to approach this issue. I even double-checked my imports. Here is the code:
import React, { Component } from "react";
import { ScrollView, Text, FlatList } from 'react-native';
import Mission from './Mission';
import PARTNERS from '../shared/partners';
import { ListItem } from 'react-native-elements';
class About extends Component {
constructor(props) {
super(props);
this.state = {
partners: PARTNERS,
}
};
static navigationOptions = {
title: 'About Us'
}
render() {
const { navigate } = this.props.navigation;
const renderPartner = ({ item }) => {
return (
<ListItem
title={item.name}
subtitle={item.description}
leftAvatar={{ source: require('./images/bootstrap-logo.png') }}
/>
);
};
return (
<ScrollView>
<Mission />
<FlatList
data={this.state.partners}
renderItem={renderPartner}
keyExtractor={item => item.id.toString()}
/>
</ScrollView >
);
}
}
export default About;
import React, { Component } from 'react';
import { FlatList, View, Text } from 'react-native';
import { ListItem, Card } from 'react-native-elements';
import { FILMS } from '../shared/films';
/*
When working correctly, when you hit "Tap to play" in the simulated mobile device to the right, you will see a list of films from shared/films.js.
Before updating this code:
- You must be logged into your Expo account (create an account if you do not have one already)
- Use the Save button on the upper right corner to fork this Snack to your account. Name it as you please, or accept the default random name.
Share the link to your version in the forum for this code challenge.
Your challenges: 1. Fix the component by adding a constructor and adding the data imported as FILMS to the component's state
2. In the FlatList, use that state data for films in the 'data' attribute.
3. In the ListItem, add the film title as the title, and the director as the subtitle.
4. Update films.js to add a third film of your choice.
Bonus Challenge: Write a custom view in the ListItem subtitle to show more details about each film, such as the release year, genre, language.
*/
class FilmCatalogue extends Component {
constructor(props) {
super(props);
this.state = {
films: FILMS
}
}
render() {
const renderFilm = ({item}) => {
return (
<ListItem
title={item.title}
titleStyle={{fontWeight: 700, color: 'dark-grey'}}
subtitle={
<View >
<Text style={{fontStyle: "italic", fontWeight: 500}}>{item.director}</Text>
<Text>{item.category}</Text>
<Text>{item.language}</Text>
</View>
}
rightSubtitle={item.year}
bottomDivider
/>
);
};
return (
<Card title="Film Catalogue">
<FlatList
data={this.state.films}
renderItem={renderFilm}
keyExtractor={item=>item.id.toString()}
/>
</Card>
);
}
}
export default FilmCatalogue;
i used this on an expo snack to display a list of the files i had in this file (the Film Catalogue Component.js)
hope this kind of helps!
Related
import React from 'react';
import {FlatList, Text, Button, ScrollView, View, ListView} from 'react-native';
import axios from 'axios';
class ChatList extends React.Component {
constructor(props) {
super(props);
this.state = { data:[], refreshing:false};
}
async componentDidMount(){
this._getChatList();
console.log("Received Data")
}
_getChatList(){
axios.get('http://10.0.2.2:5000/app_log')
.then((response) => { this.setState({ data: response.data.data}); console.log(response.data)})
.catch((error)=>{console.log("Api call error");alert(error.message);});
console.log(this.state);
}
_keyExtractor (item, index) {
return index.toString();
}
render() {
return(
<FlatList
data={this.state.data}
keyExtractor={this._keyExtractor.bind(this)}
renderItem={({item}) => (<Text>{item.message} FROM {item.sender} </Text>)}
extraData={this.state}
horizontal={false}
/>
);
}
}
export default ChatList;
I've tried putting this component in a ScrollView and it gives a warning, but other similar questions make it seem like it should just scroll without any modification. I'm not really sure what I'm doing.
I think you need to set a style to the flatlist in order to limit its height and prevent it grows while items are added. The simplest way would be to set the style to fill the available space like:
<FlatList
style={{ flex: 1 }}
...
/>
Once the Flatlist content reach that limit, stops growing and you'll be able to scroll.
Since Flatlist has a scrollview internally, is not a common use case to wrap a flatlist inside a scrollview.
Cheers!
I have an array with different values in state within my component.
I want to dynamically render different sections of an array to the same component but on different pages of my react app.
i.e Pass props down to Component that renders the first title of the array on one page but then render the second title on another page.
Can anyone help?
import React from 'react';
import ChartItem from './chart-item.component.js'
import Popup from './modal/index.js'
//styles
import './chart-slides.styles.css'
class Chart extends React.Component {
constructor() {
super();
this.state = {
sections: [
{
title: 'How do you compare to the competition?',
id: 'chart1',
iframeUrl: 'https://app.chattermill.io/c/f4a52535-b2b9-4d71-9ac7-e198c9452e3f?compact=true'
},
{
title: 'Main drivers of positive sentiment sentiment are brand, service, and app exeprience. While bugs and security features are big drivers of negative sentiment',
id: 'chart2',
iframeUrl: 'https://app.chattermill.io/c/f4a52535-b2b9-4d71-9ac7-e198c9452e3f?compact=true'
},
{
title: 'Scroll through the feedback to see the pain points for customers',
id: 'chart3',
iframeUrl: 'https://app.chattermill.io/c/f4a52535-b2b9-4d71-9ac7-e198c9452e3f?compact=true'
}
]
};
}
render() {
return (
<div>
{this.state.sections.map(({ id, title, iframeUrl }) => (
<ChartItem key={id} title={title} url={iframeUrl} />
))}
<Popup/>
</div>
);
}
}
export default Chart;
How can I only render the first section from my array in this component below? The component below will be showed in multiple pages within the app.
import React from 'react';
import Popup from '../modal/index.js'
import { Heading } from 'rebass'
import './chart-slides.styles.css'
import Iframe from 'react-iframe'
const ChartItem = ({ title, iframeUrl, id }) => (
<div>
<a className="demo-btn" id="demo-btn-chart1" href="https://app.hubspot.com/meetings/jack123/presentation" target="_blank" rel="noopener noreferrer"> Book Demo</a>
<Heading fontSize="2.8vh" textColor="secondary" className="mobile-chart-title" as='h1'>
{title}
</Heading>
<Iframe
url={iframeUrl}
className="iframe-container"
/>
</div>
);
export default ChartItem
This is my first post so be gentle if i wasn't specific enough or made stupid mistake
So i am building a shop for my semester project in ReactJS(basic Reactjs: no redux or any database), and if it is important i just started to learn about JS and REACT.
I"m using AntDesign UI and controlling the routes through react-router-dom, this is my file tree just for the understanding.
I have statefull component that return a cart icon with badge and this component is called from the Header.
lets say i"m inside the landingpage component which located in the folder src->landingpage, and each press on a specific button there should be increment the badge by 1.
now the problem is that i can see the badge increment only after clicking and not in "real time" on the header, how do i make it work in real time through any component?
Cart(badge).js code->
import React, { Component } from "react";
import { Icon, Col, Badge, Button, Switch } from 'antd';
import CartCount from '../CartCount'
const ButtonGroup = Button.Group;
class Cart extends Component {
constructor() {
super();
this.state = {
count: 0,
show: true,
}
};
componentDidMount() {
var counter1 = JSON.parse(localStorage.getItem("Carts"))
if (counter1 != this.state.count) {
this.setState({ count: counter1 })
}
}
componentDidUpdate() {
var counter1 = JSON.parse(localStorage.getItem("Carts"))
if (counter1 != this.state.count) {
this.setState({ count: counter1 })
}
}
render() {
return (
<Col offset={23}>
<Badge count={this.state.count}>
<span style={{ fontSize: "50px" }} className="head-example"><Icon type="shopping-cart" /></span>
</Badge>
</Col>
)
}
}
export default Cart;
Header(contain badge inside).js code->
import React, { Component } from 'react';
import { Link } from "react-router-dom";
import { Layout } from 'antd';
import Login from '../login/login'
import {withRouter} from 'react-router'
import Cart from '../CartIndex/Cart/Cart'
import { Row, Col, Button, Tabs, Icon } from 'antd';
import './Header.css'
class Header extends Component {
state=({
count: 0,
reload: false
})
render() {
const { Header } = Layout;
return (
<div>
{/*Login section*/}
<Row>
<Col span={24}>
<Login />
</Col>
</Row>
{/*Header section*/}
<Row>
<Header style={{ fontFamily: 'Anton', fontSize: "50px" }}>
<Col span="23">
<a style={{ color: "white" }} href="/">Store</a>
</Col>
<Link to="/CartIndex"><Cart/></Link>
</Header>
</Row>
</div>
);
}
}
export default withRouter(Header)
the onClickHandler function im doing in the landingpage->
onCartHandler = () => {
if (localStorage.getItem("Carts")) {
var counter1 = JSON.parse(localStorage.getItem("Carts"))
counter1 += 1;
localStorage.setItem("Carts", counter1)
}
else {
var Counter = JSON.stringify(1)
localStorage.setItem("Carts", Counter)
}
message.success('Successfully added to cart')
}
I hope you guys can resolve and make me understand what i did wrong or didn't even knew from the first place, i researched about all the lifecycle components but it was to generic for me to understand without see code examples.
Thanks a-lot and have a great day in the office
You badge counter is bound to your component state in Cart(badge).js.
This is where it's interesting to understand component lifecycle, i know it can be hard to understand but here is an article about it : https://blog.bitsrc.io/understanding-react-v16-4-new-component-lifecycle-methods-fa7b224efd7d
What is happening is a click on the badge launchs the componentDidUpdate function from your component lifecycle, this is why it get updated from searching in your local storage. There is not direct data binding between your local storage and this.state.count from your component, this is all made with your component lifecycle.
Now to correct this there is multiple solutions, one way or another you need to update your component state, or use some other mechanic than state, for example a Redux Store ( yeah this is more to learn again ).
I am trying to load my parent component from child component on button press. But it's not rendering the parent components from btnPress method. I am not getting any error.
onButtonPress
<Button onPress={() => btnPress(parent_id, id)}>
<Icon name="arrow-forward" />
</Button>
btnPress Function
function btnPress(parent_id, id) {
const App = () => (
//I have tried this way but this didn't work. No any error, i can see log on console
<Container>
<Headerc headerText={'Fitness sdaf'} />
<ExerciseList pId={parent_id} mId={id} />
</Container>
);
console.log(id);
AppRegistry.registerComponent('weightTraining', () => App);
}
full code(child component)
import React from 'react';
import { Right, Body, Thumbnail, Container, ListItem, Text, Icon } from 'native-base';
import { AppRegistry
} from 'react-native';
import Headerc from './headerc';
import ExerciseList from './exerciseList';
import Button from './Button';
const ExerciseDetail = ({ exercise }) => {
const { menu_name, menu_icon, parent_id, id } = exercise;
function NumberDescriber() {
let description;
if (menu_icon === 'noimg.jpg') {
description = `http://www.xxxxxx.com/uploads/icons/${menu_icon}`;
} else if (menu_icon === 'noimg.jpg') {
description = menu_icon;
} else {
description = `http://www.xxxxx.com/uploads/icons/${menu_icon}`;
}
return description;
}
function btnPress(parent_id, id) {
const App = () => (
<Container>
<Headerc headerText={'Fitness sdaf'} />
<ExerciseList pId={parent_id} mId={id} />
</Container>
);
console.log('-------------------------------');
console.log(id);
console.log('+++++++++++++++++++++++++++');
AppRegistry.registerComponent('weightTraining', () => App);
}
return (
<ListItem>
<Thumbnail square size={80} source={{ uri: NumberDescriber() }} />
<Body>
<Text>{menu_name}</Text>
<Text note> {menu_name} exercise lists</Text>
</Body>
<Right>
<Button onPress={() => btnPress(parent_id, id)}>
<Icon name="arrow-forward" />
</Button>
</Right>
</ListItem>
);
};
export default ExerciseDetail;
Please do let me know, if you need more information.
I would not suggest doing that way, it look totally anti-pattern and not.
better try with navigation or create a pattern like this
inside your index.js or index.android.js or index.ios.js
import App from './App' //your app level file
AppRegistry.registerComponent('weightTraining', () => App);
now in your app js file
export default App class extends React.Component{
constructor(props){
super(props);
this.state ={
component1:false,
component2:true,
}
}
btnPressed =()=>{
//handle state update logic here
}
render(){
if(this.state.component1) return <Component1/>
return <Component2/>
}
}
**** not the best solution available, play around and you will get best
To navigate from this component to your parent component unless you want to implement your own navigation which isn't recommended, you should look into one that's already built and adopted by many in the react-native ecosystem.
Some of the biggest ones:
React Native Navigation
React Navigation
React Native Router
I personally highly recommend option number 1, since it seems to be the most production tested and production ready implementation out there
I'm trying to make a simple quiz app in React Native:
App.js
export default class App extends React.Component {
constructor(props) {
super(props);
this.quizData = [
{
question: 'Who wrote A Game Of Thrones?',
correctAnswer: 'George RR Martin',
possibleAnswers: ['JK Rowling', 'Phillip Pulman', 'George RR Martin' ]
},
];
}
render() {
return (
<View style={styles.container}>
<MultiChoice answers={this.quizData[0].possibleAnswers}/>
</View>
);
}
}
And my MultiChoice component:
import React, { Component } from 'react';
import { StyleSheet, Text, View } from 'react-native';
class MultiChoice extends Component {
render() {
return(
<View>
<Text style={styles.button}>{ this.props.answers.map(answer => answer) }</Text>
</View>
)
}
}
const styles = StyleSheet.create({
button: {
backgroundColor: 'blue',
width: 200,
height: 40,
}
})
export default MultiChoice;
I don't get any errors and all the elements of the array are displayed in the same button, but I would like to have three separate buttons. I wrote the same code in React and it worked, but in React Native it is not working.
Currently, your map just returns each element, unmodified -- it does nothing. It will then create one single <Text> component with all the text. Just have the map operation return a separate <Text> component for every element to achieve separate buttons:
{ this.props.answers.map(answer => <Text style={styles.button}>{answer}</Text>) }
And this will create separate <Text> components with the strings.