Fetching data from function into <View> component inside the render method - javascript

I tried to fetch the data from function inside render, when I use alert() it works, but when I try to return real text it not shown any thing
the code I work with:
export default class App extends Component {
renderResualts(){
db.find({}, function (err, docs) {
return docs.map(function(d){
return(
<Text>{d.name}</Text>
)
})
})
}
render() {
return (
<View style={styles.container}>
{ this.renderResualts() }
</View>
);
}
}
--
UPDATED CODE:
export default class App extends Component {
constructor(props){
super(props)
this.state = {graves:[]}
}
componentDidMount(){
db.find({}, function (err, docs) {
this.setState({graves:docs})
})
}
renderResults(){
return this.state.graves.map(grave =>
<Text>{grave.name}</Text>
)
}
render() {
return (
<View style={styles.container}>
{ this.renderResults() }
</View>
);
}
}
It should be shown these data :
{
_id: 1,
name: 'Parturient',
year: 2017
}, {
_id: 2,
name: 'Dapibus',
year: 2017
}
inside text like so: ParturientDapibus

try this
renderResults(){
return (
<View>
this.state.graves.map(grave =>
<Text>{grave.name}</Text>
)
</View>
);
}

By passing the data to State like so:
export default class App extends Component {
constructor(props){
super(props)
this.state = {graves:[]}
}
componentDidMount(){
db.find({}, (err, docs)=> {
this.setState({graves:docs})
})
}
renderResults(){
return this.state.graves.map(grave =>
<Text key={grave._id}>{grave.name}</Text>
)
}
render() {
return (
<View style={styles.container}>
{ this.renderResults() }
</View>
);
}
}

Related

data from object not rendering in any component in react native [duplicate]

I'm trying to get data from an array and using map function to render content. Look at
**{this.lapsList()}**
and the associated
**lapsList()**
function to understand what I'm trying to do. The result is nothing is displaying (Views under view, etc.) Here is my simplified code:
class StopWatch extends Component {
constructor(props) {
super(props);
this.state = {
laps: []
};
}
render() {
return (
<View style={styles.container}>
<View style={styles.footer}>
<View><Text>coucou test</Text></View>
{this.lapsList()}
</View>
</View>
)
}
lapsList() {
this.state.laps.map((data) => {
return (
<View><Text>{data.time}</Text></View>
)
})
}
_handlePressLap() {
console.log("press lap");
if (!this.state.isRunning) {
this.setState({
laps: []
})
return
}
let laps = this.state.laps.concat([{'time': this.state.timeElapsed}]);
this.setState({
laps: laps
})
console.log(laps);
}
}
Don't forget to return the mapped array , like:
lapsList() {
return this.state.laps.map((data) => {
return (
<View><Text>{data.time}</Text></View>
)
})
}
Reference for the map() method: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
Try moving the lapsList function out of your class and into your render function:
render() {
const lapsList = this.state.laps.map((data) => {
return (
<View><Text>{data.time}</Text></View>
)
})
return (
<View style={styles.container}>
<View style={styles.footer}>
<View><Text>coucou test</Text></View>
{lapsList}
</View>
</View>
)
}
lapsList() {
return this.state.laps.map((data) => {
return (
<View><Text>{data.time}</Text></View>
)
})
}
You forgot to return the map. this code will resolve the issue.

Passing navigation from function to component throws Typerror

I have the following function:
export default function InstitutionInfoScreen({route, navigation}) {
const { title, image, logo, location, phone, email } = route.params;
return (
<ScrollView >
<View style={styles.whiteContainer}>
<InstItem navigation={navigation}/>
</View>
</ScrollView>
);
}
Turns out I want InstItem to get the navigation parameter, because I need it for my SliderEntry component.
InstItem looks like this:
class InstItem extends React.Component {
constructor(props){
super(props);
this.state = {
activeSlide: SLIDER_1_FIRST_ITEM
};
}
_renderItemWithParallax ({item, index}, parallaxProps) {
return (
<SliderEntry
navigate={this.props.navigation}. <-- THIS IS THE ISSUE
type="institution"
data={item}
even={(index + 1) % 2 === 0}
parallax={true}
parallaxProps={parallaxProps}
/>
);
}
render(){
return (
<View style={styles.whiteContainer}>
<Carousel
ref={c => this._slider1Ref = c}
data={DATA2}
renderItem={this._renderItemWithParallax}
sliderWidth={sliderWidth}
itemWidth={itemWidth}
hasParallaxImages={true}
firstItem={SLIDER_1_FIRST_ITEM}
inactiveSlideScale={0.94}
inactiveSlideOpacity={0.7}
// inactiveSlideShift={20}
containerCustomStyle={styles.slider}
contentContainerCustomStyle={styles.sliderContentContainer}
loop={true}
loopClonesPerSide={2}
onSnapToItem={(index) => this.setState({ activeSlide: index }) }
/>
<Pagination
dotsLength={DATA2.length}
activeDotIndex={this.state.activeSlide}
containerStyle={styles.paginationContainer}
dotColor={'rgba(46, 49, 49, 1)'}
dotStyle={styles.paginationDot}
inactiveDotColor={colors.navyblue}
inactiveDotOpacity={0.4}
inactiveDotScale={0.6}
carouselRef={this._slider1Ref}
tappableDots={!!this._slider1Ref}
/>
</View>
);
}
}
However I always get:
typeerror undefined is not an object (evaluating 'this.props.navigation')
I´ve tried to use "navigation" directly instead of "this.props.navigation" but that doesn't work either. How can I fix this?

How to pass an array from a parent component to child component using props in React Native?

I want to paas "subjects" array from SubjectsScreen to MarkAttendanceScreen and display the array items as a FlatList.
Parent Component
export default class SubjectsScreen extends Component {
state = {
subjects: ["A", "B"]
};
render() {
return (
...
<MarkAttendanceScreen subjectsArray={this.state.subjects} />
);
}
}
Child Component
export default class MarkAttendanceScreen extends Component {
constructor(props) {
super(props);
this.state = {
subjects: []
};
}
componentDidMount() {
this.setState({ subjects: this.props.subjectsArray });
}
render() {
return (
<FlatList>
{ this.props.subjects.map((item, key)=>(
<Text key={key}> { item } </Text>)
)}
</FlatList>
);
}
}
Using props was giving error when using FlatList with map.
Works fine when extracting value directly from AsyncStorage.
export default class MarkAttendanceScreen extends Component {
state = {
subjects: [],
text: ""
}
componentDidMount() {
Subjects.all(subjects => this.setState({ subjects: subjects || [] }));
}
render() {
return (
<View>
<FlatList
data={ this.state.subjects}
renderItem={({item}) => {
return (
<View>
<Text> { item.text } </Text>
</View>
)
}}
keyExtractor={ (item, index) => index.toString()}
/>
</View>
);
}
}
let Subjects = {
convertToArrayOfObject(subjects, callback) {
return callback(
subjects ? subjects.split("\n").map((subject, i) => ({ key: i, text: subject })) : []
);
},
convertToStringWithSeparators(subjects) {
return subjects.map(subject => subject.text).join("\n");
},
all(callback) {
return AsyncStorage.getItem("SUBJECTS", (err, subjects) =>
this.convertToArrayOfObject(subjects, callback)
);
},
};
this.props.subjects does not exist, but you did set the state in componentDidMount. In the FlatList use this.state.subject.map.
render() {
return (
<FlatList>
{ this.state.subjects.map((item, key)=>(
// ^here
<Text key={key}> { item } </Text>)
)}
</FlatList>
);
}
You must use the same key name that you used while passing down data to child component e.g. in your case you used key subjectsArray here and You don't need to store this first in state and then use unless you want to update it later.
<MarkAttendanceScreen subjectsArray={this.state.subjects} />
So in your child component, it will be
<FlatList>
{this.props.subjectsArray.map((item, key)=>(
<Text key={key}> { item } </Text>
))}
</FlatList>
D. Smith is correct, you need to change that line to this.state.subjects.map But could also just remove the state variable from the Child Component and use the array directly from props.
export default class MarkAttendanceScreen extends Component {
constructor(props) {
super(props);
}
render() {
return (
<FlatList>
{ this.props.subjectsArray.map((item, key)=>(
<Text key={key}> { item } </Text>)
)}
</FlatList>
);
}
}
Update:
Flatlists need to be defined like this:
<FlatList
data={ this.props.subjectsArray }
renderItem={({item}) => {
return (
<Text> { item } </Text>)
)
}}
keyExtractor={(item, index) => index}
/>
or you can use it the way you have it and remove the flatlist like:
return this.props.subjectsArray.map((item, key)=>(
<Text key={key}> { item } </Text>)
)}

React Native Run Child Reference Method From Another Component

I am trying to run a component method of another component. I am trying this using react ref. I am also following this link:
https://medium.freecodecamp.org/react-changing-state-of-child-component-from-parent-8ab547436271 But my structure is a bit more complicated.
List.js
class List extends Component {
constructor(){
super()
this.LoadCounterElement = React.createRef()
}
render(){
return(
<View>
<ItemGenerator />
<LoadCounter ref={this.LoadCounterElement}/>
</View>
)
}
}
function mapStateToProps(state) {
return {
counter: state.counter.counter
}
}
function mapDispatchToProps(dispatch) {
return {
increaseCounter: () => dispatch({ type: 'INCREASE_COUNTER' }),
decreaseCounter: () => dispatch({ type: 'DECREASE_COUNTER' }),
}
}
export default connect(mapStateToProps)(List);
ItemGenerator.js
class ItemGenerator extends Component {
render() {
return (
<ScrollView>
{
this.state.data.map((item, index) => {
return(<ItemList navigate={this.props.navigate} data={item} key={index}/>)
})
}
</ScrollView>
)
}
}
LoadCounter.js
class LoadCounter extends Component {
constructor(props) {
super(props)
this.state = {
count : 0,
}
}
componentDidMount() {
this._renderCount()
}
_renderCount = () => {
this.setState({count:this.props.counter})
}
render(){
return(
<View>
<Text>{this.state.count}</Text>
</View>
)
}
}
function mapStateToProps(state) {
return {
counter: state.counter.counter
}
}
export default connect(mapStateToProps)(withNavigation(LoadCounter));
ItemList.js
class ItemList extends Component {
render() {
return(
<View>
<TouchableOpacity onPress={() => {
this.props.increaseCounter()
this.LoadCounterElement.current._renderCount()
}}>
<Card containerStyle={{margin: 0}}>
<View style={{flex:1, flexDirection:'row', height:70, alignItems:'center', justifyContent:'space-between'}}>
<View style={{flexDirection:'row', alignItems:'center', width:'55%'}}>
<View style={{flexDirection:'column', marginLeft:10}}>
<Text style={{...}}>{this.props.data.name}</Text>
</View>
</View>
</View>
</Card>
</TouchableOpacity>
</View>
)
}
}
function mapDispatchToProps(dispatch) {
return {
increaseCounter: () => dispatch({ type: 'INCREASE_COUNTER' }),
decreaseCounter: () => dispatch({ type: 'DECREASE_COUNTER' }),
}
}
export default connect(mapStateToProps)(ItemList);
counterReducer.js
const initialState = {
counter: 1
}
const counterReducer = (state = initialState, action) => {
switch (action.type) {
case 'INCREASE_COUNTER':
return { counter: state.counter + 1 }
case 'DECREASE_COUNTER':
return { counter: state.counter - 1 }
}
return state
}
export default counterReducer;
As you can see in ItemLiist Component, i am trying to run _renderCount method which is in Component LoadCounter. But its not working. Kindly guide what i am missing?
The problem here is that you have some data in child component that should be reflected in a parent component. I would recommend that you move the shared state in the parent component or to the reducer state.
It is odd that you are using an action creator to increment/decrement counts - which I am thinking that updates some reducer state. If this is the case, why store that state in the local component state again ? You could just read the counter state from the reducer in your parent component.
Parent.js
class Parent extends React.Component {
render() {
return (
<div>
<span>{this.props.count}</span>
</div>
);
}
}
const mapStateToProps = state => ({
count: state.yourCountReducer.count,
});
export default connect(mapStateToProps)(Parent);
Child.js
class Child extends React.Component {
render() {
return (
<div>
<button onClick={() => this.props.increaseCounter()}>+</button>
<button onClick={() => this.props.decreaseCounter()}>-</button>
</div>
);
}
}
const mapDispatchToProps = dispatch => ({
increaseCounter: () => dispatch({ type: 'INCREASE_COUNTER' }),
decreaseCounter: () => dispatch({ type: 'DECREASE_COUNTER' }),
});
export default connect(null, mapDispatchToProps)(Child);
This way, the parent component will show the updated counter state when the child component updates the count. From your sample code, I am not sure if there is any good reason to store a shared reducer state in any component's local state.

Passing object to reusable view get error: null is not object (evaluating ...)

I create a Component which is getting data from server then shows data on the screen. The screen look good when I use react-native views directly.
After that, I refactor the code to make it reusable by moving a snippet of code to a new component (TwoGroupItemsView):
export class MainComponent extends Component {
componentDidMount() {
return fetch('https://mycompany.com/items')
.then(res => res.json())
.then(json => {
this.setState({
isLoading: false,
items: json.data,
}, function(){
});
}
}
render() {
return (
<View>
<View>
{
this.state.items != null &&
<TwoGroupItemsView title={'Group 1'} items={this.state.items}/>
}
</View>
</View>
);
}
}
class TwoGroupItemsView extends View {
constructor(props) {
super(props);
}
render() {
return (
<View style={{marginTop: 16}}>
//... FlatList for items array
</View>
)
}
}
I always get:
TypeError: null is not an object
When evaluating 'this.state.items'.
Can you show me the way to create my own reusable views?
Your state is being set asynchronously. Try explicitly initializing it before the Promise resolves. Some possibilities below.
Declaring the initial state:
export class MainComponent extends Component {
state = {
isLoading: true, // sample values
items: null
}
Or setting in the constructor:
export class MainComponent extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true, // sample values
items: null
};
}
Or strengthening the guards:
render() {
return (
<View>
<View>
{
this.state && this.state.items != null &&
<TwoGroupItemsView title={'Group 1'} items={this.state && this.state.items}/>
}
</View>
</View>
);
}
Re write your render function.
render() {
return (
<View>
<View>
{
this.state.items ?
<TwoGroupItemsView title={'Group 1'} items={this.state.items}/> : null
}
</View>
</View>
);
}

Categories

Resources