I'm working on a code that will give a TodoList in React-Native, my code doesn't create an error but when I want to change a label, the code duplicates my state. I can't find where is my mistake, can someone help me please?
Apps.js
`
import React, {Component, useState} from 'react';
import {View,Text,Button, StyleSheet} from 'react-native';
import TodoList from './TodoList';
class Apps extends Component {
state={
todos:[
{id:1,label:'Buy some milk'},
{id:2,label:'Learn some React'}
]
}
newTodo = ()=>{
this.setState({count:this.state.count+1})
this.setState({todos:[...this.state.todos,...[{id:this.state.count+1,label:'New Task'}]]})
}
updateTodoLabel=(todoId,label)=>{
const{todos}=this.state
const todoIndex=todos.findIndex(t=>t.id===todoId)
const todosBefore=todos.slice(0,todoIndex)
const todosAfter=todos.slice(todoIndex+1)
const newtodo={...todos[todoIndex],label}
this.setState({
todos:[...todosBefore,newtodo,...todosAfter]
})
}
render(){
const {todos} = this.state
return(
<View style={styles.container}>
<TodoList todos={todos} updateTodoLabel={this.updateTodoLabel}/>
<Button title="Add" onPress={this.newTodo}/>
</View>
)
}
}
// ...
const styles=StyleSheet.create({
container:{
flex:1,
marginTop:25
}
})
export default Apps
`
Todo.js
`
//src/components/Todo.js
import { Component, Fragment } from 'react';
import {
View,
Text,
StyleSheet,
Button,
TextInput,
TouchableOpacity,
} from 'react-native';
class Todo extends Component {
state = {
editMode: false,
label: this.props.todo.label,
};
renderEditMode = () => {
const { label } = this.state;
return (
<Fragment>
<TextInput
style={[styles.editInput, styles.todoLabel]}
value={label}
onChangeText={this.onChange}
autoFocus
/>
<Button title="Save" onPress={this.onSavePress} />
<Button title="Cancel" onPress={this.onCancelPress} />
</Fragment>
);
};
onPressButton = () => {
const { updateTodoLabel } = this.props;
const { label } = this.state;
updateTodoLabel(label + '✅');
this.setState({
editMode: false,
});
};
render() {
const { editMode } = this.state;
return (
<View style={styles.todo}>
{editMode ? this.renderEditMode() : this.renderViewMode()}
</View>
);
}
renderViewMode = () => {
const { todo } = this.props;
return (
<Fragment>
<TouchableOpacity onPress={this.onPressButton}>
<Text style={styles.todoLabel}>{todo.label}</Text>
</TouchableOpacity>
<Button title="Edit" onPress={this.onEditPress} />
</Fragment>
);
};
onEditPress = () => {
this.setState({
editMode: true,
});
};
onChange = (label) => {
this.setState({ label });
};
onSavePress = () => {
const { updateTodoLabel } = this.props;
const { label } = this.state;
updateTodoLabel(label);
this.setState({
editMode: false,
});
};
onCancelPress = () => {
this.setState({
editMode: false,
label: this.props.todo.label,
});
};
}
const styles = StyleSheet.create({
todo: {
padding: 10,
borderTopWidth: 1,
borderStyle: 'solid',
borderColor: 'lightgray',
},
todoLabel: {
fontSize: 18,
padding: 10,
flex: 1,
},
});
export default Todo;
`
TodoList.js
`
//src/components/TodoList.js
import React from 'react';
import {View, StyleSheet,Button} from 'react-native';
import Todo from './Todo';
const TodoList=({todos, updateTodoLabel})=>(
<View style={styles.todoList}>
{todos.map(todo =>(
<Todo
todo={todo}
updateTodoLabel={label=>updateTodoLabel(todo.id,label)}
key={todo.id}/>
))}
</View>
)
const styles = StyleSheet.create({
todoList:{
flex:1,
alignItems:'stretch'
}
})
export default TodoList
`
I trying to give a precise way of the label or to just change the label and to change the old state by the new state but I'm a beginner and I only found errors in this ways.
I found my error, that's was only a mistake on the todos of my state in the Apps.js, I need to get a count:2 after the todos.
state={
todos:[
{id:1,label:'Buy some milk'},
{id:2,label:'Learn some React'}
],count:2
}
Related
So im new at react native and i built an custom text input that gives suggestions by following a tutorial.But now i cant use onChange in that custom text input.I tried to create a state in App.js and change it in AutoCompleteText.js file but didnt worked.How can i get the value inmy custom text input ?
my App.js file :
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import AutoCompleteText from './AutoCompleText'
import './AutoCompleteText.css';
export default function App() {
return (
<View style={styles.container}>
<View style={styles.AutoComp}>
<AutoCompleteText items={['Ali','Veli','Ahmet']} />
</View>
<StatusBar style="auto" />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
AutoComp:{
width:600
}
});
my AutoCompleteText.js file
import React from 'react'
import './AutoCompleteText.css';
export default class AutoCompleteText extends React.Component{
constructor(props){
super(props);
this.state={
suggestions:[],
text:'',
};
}
onTextChanged = (e) =>{
const {items} = this.props;
const value = e.target.value;
let suggestions = [];
if (value.length > 0){
const regex = new RegExp(`^${value}`,'i');
suggestions = items.sort().filter(v => regex.test(v));
}
this.setState(() => ({ suggestions , text: value }));
}
suggestionSelected(value){
this.setState(() =>({
text: value,
suggestions:[],
}) )
}
renderSuggestions(){
const {suggestions} = this.state;
if (suggestions.length === 0){
return null;
}
return(
<ul>
{suggestions.map((item) => <li onClick={() => this.suggestionSelected(item)}>{item}</li>)}
</ul>
);
}
render(){
const { text } = this.state;
return(
<div className="AutoCompleteText">
<input value={text} onChange={this.onTextChanged} type ='text'/>
{this.renderSuggestions()}
</div>
)
}
}
hi Ülkü Tuncer Küçüktaş,
You are writing the wrong syntax. You are mixing the syntax of react native with react. In react native for textinput, you should use the TextInput Component(Built in component from docs).
The syntax of react native TextInput look like below
import React from 'react';
import { TextInput } from 'react-native';
const UselessTextInput = () => {
const [value, onChangeText] = React.useState('Useless Placeholder');
return (
<TextInput
style={{ height: 40, borderColor: 'gray', borderWidth: 1 }}
onChangeText={text => onChangeText(text)}
value={value}
/>
);
}
export default UselessTextInput;
I am new to this so I hope this is the right place to get help!
As titled, executing this code is giving me the "Too many re-renders" error on React.
I have tried going through all lines and checking my hooks repeatedly, but nothing seems to work.
I am guessing this is happening due to useEffect, so pasting the code for the relevant components below:
UseResults:
import { useEffect, useState } from 'react';
import yelp from '../api/yelp';
export default () => {
const [results, setResults] = useState([]);
const [errorMessage, setErrorMessage] = useState('');
const searchApi = async () => {
try {
const response = await yelp.get('/search', {
params: {
limit: 50,
term,
location: 'san francisco'
}
});
setResults(response.data.businesses);
} catch (err) {
setErrorMessage('Something went wrong')
}
};
useEffect(() => {
searchApi('pasta');
}, []);
return [searchApi, results, errorMessage];
}
SearchScreen:
import React, { useState } from 'react';
import { Text, StyleSheet } from 'react-native';
import { ScrollView } from 'react-native-gesture-handler';
import ResultsList from '../components/ResultsList';
import SearchBar from '../components/SearchBar';
import useResults from '../hooks/useResults';
const SearchScreen = (navigation) => {
const [term, setTerm] = useState('');
const [searchApi, results, errorMessage] = useResults();
const filterResultsByPrice = (price) => {
return results.filter(result => {
return result.price === price;
});
};
return <>
<SearchBar
term={term}
onTermChange={setTerm}
onTermSubmit={searchApi()}
/>
{errorMessage ? <Text>{errorMessage}</Text> : null}
<Text>We have found {results.length} results</Text>
<ScrollView>
<ResultsList
results={filterResultsByPrice('$')}
title="Cost Effective"
navigation={navigation}
/>
<ResultsList
results={filterResultsByPrice('$$')}
title="Bit Pricier"
navigation={navigation}
/>
<ResultsList
results={filterResultsByPrice('$$$')}
title="Big Spender"
navigation={navigation}
/>
</ScrollView>
</>
};
const styles = StyleSheet.create({});
export default SearchScreen;
ResultsList:
import React from 'react';
import { View, Text, StyleSheet, FlatList } from 'react-native';
import { TouchableOpacity } from 'react-native-gesture-handler';
import ResultsDetail from './ResultsDetail';
const ResultsList = ({ title, results, navigation }) => {
return (
<View style={styles.container} >
<Text style={styles.title}>{title}</Text>
<FlatList
horizontal
showsHorizontalScrollIndicator={false}
data={results}
keyExtractor={result => result.id}
renderItem={({ item }) => {
return (
<TouchableOpacity onPress={() => navigation.navigate('ResultsShow')}>
<ResultsDetail result={item} />
</TouchableOpacity>
)
}}
/>
</View>
);
};
const styles = StyleSheet.create({
title: {
fontSize: 18,
fontWeight: 'bold',
marginLeft: 15,
marginBottom: 5
},
container: {
marginBottom: 10
}
});
export default ResultsList;
TIA!
I have a project where i can have n-number of input field. After when i add 200 items, it starts lagging after that. Demo : https://testcreate.vivekneel.now.sh/create (To test: Focus last input and try pressing enter button to create new input)
Source Code. : https://github.com/VivekNeel/Create-Test
This is my main container :
import React, { useState } from "react";
import CreateTerms from "./CreateTerms";
import { initTerms, contructTermObject } from "./utils";
import { Container } from "#material-ui/core/";
const CreateStudySetContainer = () => {
const [terms, setTerms] = useState(initTerms);
const [inputIdToFocus, setInputIdToFocus] = useState(null);
const handleCreateTerm = () => {
const newTerm = contructTermObject(terms.length + 1, 2);
const newTerms = [...terms, newTerm];
setInputIdToFocus(terms.length + 1);
setTerms(newTerms);
};
console.log("....rendering");
return (
<Container maxWidth={"md"}>
<CreateTerms
terms={terms}
inputIdToFocus={inputIdToFocus}
createTerm={handleCreateTerm}
/>
;
</Container>
);
};
export default CreateStudySetContainer;
This the CreateTerms code :
import React from "react";
import CreateFacts from "./CreateFacts";
import { withStyles, Card } from "#material-ui/core/";
import ContentItemRow from "./ContentItemRow";
const styles = () => ({
card: {
marginBottom: 16,
},
});
const CreateTerms = (props) => {
const { terms, classes, createTerm, inputIdToFocus } = props;
return (
<div className={classes.container}>
{terms.map(({ node: { term } }, index) => {
return (
<Card key={term.id} className={classes.card}>
<p>{index}</p>
<ContentItemRow
autoFocus={term.id === inputIdToFocus}
createTerm={createTerm}
term={term}
/>
;
</Card>
);
})}
</div>
);
};
export default withStyles(styles)(CreateTerms);
This is ContentItemRow :
import React from "react";
import CreateFacts from "./CreateFacts";
import { withStyles } from "#material-ui/core/";
import ContentEditor from "./ContentEditor";
const styles = {
container: {
display: "flex",
flexDirection: "row",
alignItems: "center",
justifyContent: "flex-start",
},
term: {
marginRight: 16,
flex: 1,
},
facts: {
flex: 1,
},
};
const ContentItemRow = (props) => {
const { term, classes, createTerm, autoFocus } = props;
return (
<div className={classes.container}>
<div className={classes.term}>
<ContentEditor
autoFocus={autoFocus}
createTerm={createTerm}
placeholder={"New term"}
/>
</div>
<div className={classes.facts}>
{term.facts.map(({ fact }) => {
return (
<ContentEditor
key={fact.id}
createTerm={createTerm}
placeholder={"New fact"}
/>
);
})}
</div>
</div>
);
};
export default withStyles(styles)(ContentItemRow);
This is ContentEditor :
import React from "react";
import { TextField } from "#material-ui/core/";
const ContentEditor = (props) => {
const { placeholder, createTerm, autoFocus } = props;
const handleOnKeyDown = (event) => {
const { keyCode } = event;
if (keyCode === 13) {
createTerm();
}
};
return (
<TextField
onKeyDown={handleOnKeyDown}
fullWidth
autoFocus={autoFocus}
placeholder={placeholder}
/>
);
};
export default ContentEditor;
When debugging, I noticed that dom updates only the last div which gets added. I don't know where the lagging is coming from.
Not sure if this will work but you can try the following:
const ContentItemRow = React.memo(function ContentItemRow (props) => {
And to prevent re creating the create term handler:
const handleCreateTerm = useCallback(() => {
setTerms((terms) => {
const newTerm = contructTermObject(
terms.length + 1,
2
);
const newTerms = [...terms, newTerm];
setInputIdToFocus(terms.length + 1);
return newTerms;
});
}, []);
When my reducer runs, the store does change to the new value, but the redux devtools shows that the store was always at the new value and never the old value. Am I mutating state in the editSnippetReducerFunction reducer or something?
const addSnippetReducerFunction = (state: any, action): any => {
return Object.assign({}, state, {
snippets: [
...state.snippets,
{
text: action.payload.text,
id: action.payload.id
}
]
})
}
const editSnippetReducerFunction = (state: any, action): any => {
const newSnippets = state.snippets.map(snippet => {
if (snippet.id === action.payload.id) {
snippet.text = action.payload.text
return snippet
} else {
return snippet
}
})
return { snippets: newSnippets, ...state}
}
const removeSnippetReducerFunction = (state: any, action): any => {
const newSnippets = state.snippets.filter(snippet => snippet.id !== action.payload.id)
return { snippets: newSnippets, history: [] }
}
export const rootReducer: any = createReducer(initialState, {
ADD_SNIPPET: addSnippetReducerFunction,
EDIT_SNIPPET: editSnippetReducerFunction,
REMOVE_SNIPPET: removeSnippetReducerFunction
})
The action is dispatched with the correct details. It is only the editSnippetReducerFunction reducer function that has this issue, The other reducers shown above do work correctly.
EDIT: It actually works if I stop using react-redux connect on the component and I move the action to the parent component which is connected and working.
The component that doesn't work when connected:
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { withStyles } from '#material-ui/core/styles'
import ListItem from '#material-ui/core/ListItem'
import ListItemIcon from '#material-ui/core/ListItemIcon'
import ListItemText from '#material-ui/core/ListItemText'
import ListItemSecondaryAction from '#material-ui/core/ListItemSecondaryAction'
import Button from '#material-ui/core/Button'
import MoreHorizIcon from '#material-ui/icons/MoreHoriz'
import CodeIcon from '#material-ui/icons/Code'
import { styles } from './snippet.style.js'
import Menu from '#material-ui/core/Menu'
import MenuItem from '#material-ui/core/MenuItem'
import { removeSnippet } from '../app/action'
import { bindActionCreators } from 'redux'
import type { Dispatch } from 'redux'
import { connect } from 'react-redux'
const mapDispatchToProps = (dispatch: Dispatch): any => {
return bindActionCreators(
{
removeSnippet: removeSnippet
},
dispatch
)
}
class SnippetComponent extends Component<any, any> {
constructor(props) {
super(props)
this.state = {
anchorEl: undefined
}
}
handleClick = event => {
this.setState({ anchorEl: event.currentTarget })
}
handleClose = () => {
this.setState({ anchorEl: null })
}
handleRemove = () => {
this.props.removeSnippet({snippetId: this.props.snippet.id})
}
render = () => {
return (
<ListItem
button
onClick={() => this.props.onSnippetClick(this.props.snippet)}
className={this.props.classes.listItem}>
<ListItemIcon>
<CodeIcon />
</ListItemIcon>
<ListItemText
style={{
marginRight: '100px',
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis'
}}
primary={this.props.snippet.text}
/>
<ListItemSecondaryAction>
<Button
variant="fab"
color="primary"
aria-owns={this.state.anchorEl ? 'simple-menu' : null}
aria-haspopup="true"
onClick={this.handleClick}
className={this.props.classes.iconHover}
style={{
marginRight: '50px',
boxShadow: 'none',
color: 'white'
}}
aria-label="Add">
<MoreHorizIcon />
</Button>
<Menu
id="simple-menu"
anchorEl={this.state.anchorEl}
open={Boolean(this.state.anchorEl)}
onClose={this.handleClose}>
<MenuItem onClick={this.handleRemove}>Remove Snippet</MenuItem>
<MenuItem onClick={this.handleClose}>Share</MenuItem>
</Menu>
</ListItemSecondaryAction>
</ListItem>
)
}
}
SnippetComponent.propTypes = {
classes: PropTypes.object.isRequired,
snippet: PropTypes.object.isRequired,
addToCart: PropTypes.func.isRequired
}
const Snippet = withStyles(styles)(
connect(
undefined,
mapDispatchToProps
)(SnippetComponent)
)
export default withStyles(styles)(Snippet)
The parent component:
import React, { Component } from 'react'
import './App.css'
import brace from 'brace'
import AceEditor from 'react-ace'
import 'brace/mode/javascript'
import 'brace/theme/gruvbox'
import Button from '#material-ui/core/Button'
import AddIcon from '#material-ui/icons/Add'
import { bindActionCreators, createStore } from 'redux'
import type { Dispatch } from 'redux'
import { addSnippet, editSnippet, removeSnippet } from './action'
import { connect, Provider } from 'react-redux'
import { composeWithDevTools } from 'redux-devtools-extension'
import PropTypes from 'prop-types'
import Grid from '#material-ui/core/Grid'
import Snippet from '../snippet/Snippet'
import List from '#material-ui/core/List'
import { rootReducer } from './app.reducer.js'
import type { Props, AppState } from './app.model.js'
import { appHeaderHeight } from './app.style.js'
import { withStyles } from '#material-ui/core/styles'
import { styles } from './app.style.js'
import Header from '../header/Header'
import ConfirmDialog from '../confirm/ConfirmDialog'
// and so is this. proptypes needs it in initial state and also mapstatetoprops
const mapStateToProps = (
state: any,
ownProps: { buttonColour: string }
): any => ({
snippets: state.snippets,
history: state.history,
buttonColour: ownProps.buttonColour
})
const mapDispatchToProps = (dispatch: Dispatch): any => {
return bindActionCreators(
{
addSnippet: addSnippet,
editSnippet: editSnippet
},
dispatch
)
}
class AppComponent extends Component<Props, AppState> {
constructor(props) {
super(props)
this.state = {
width: 0,
height: 0,
editor: React.createRef(),
saveButtonDisabled: true,
editorValue: '',
open: false,
lastClickedSnippet: ''
}
}
componentDidMount = () => {
this.updateWindowDimensions()
window.addEventListener('resize', this.updateWindowDimensions)
}
componentWillUnmount = () => {
window.removeEventListener('resize', this.updateWindowDimensions)
}
updateWindowDimensions = () => {
this.setState({
width: window.innerWidth,
height: window.innerHeight
})
}
onEditorChange = editorValue => {
if (editorValue.length > 5) {
this.setState({ saveButtonDisabled: false })
} else {
this.setState({ saveButtonDisabled: true })
}
this.setState({ editorValue: editorValue })
}
onSaveButtonClick = () => {
this.setState({ saveButtonDisabled: true })
if (this.state.lastClickedSnippet) {
this.props.editSnippet({
snippetId: this.state.lastClickedSnippet.id,
snippetText: this.state.editorValue
})
this.setState({ lastClickedSnippet: undefined })
} else {
this.props.addSnippet({
text: this.state.editor.current.editor.getValue()
})
}
this.setState({ editorValue: '' })
}
onSnippetClick = (snippet: Snippet) => {
this.setState({ lastClickedSnippet: snippet })
this.setState({ open: true })
}
onDialogClose = value => {
this.setState({ value, open: false })
}
handleOk = () => {
this.setState({ editorValue: this.state.lastClickedSnippet.text })
this.onDialogClose(this.state.value)
};
handleCancel = () => {
this.setState({ lastClickedSnippet: undefined })
this.onDialogClose(this.state.value)
};
render = () => {
let allSnippets = []
if (this.props.snippets) {
allSnippets = this.props.snippets.map(snippet => (
<Snippet
snippet={snippet}
key={snippet.id}
onSnippetClick={this.onSnippetClick}
editSnippet={this.props.editSnippet}
/>
))
}
return (
<div className="App">
<ConfirmDialog
handleOk={this.handleOk}
handleCancel={this.handleCancel}
open={this.state.open}
onDialogClose={this.onDialogClose}
value={this.state.value}
/>
<Header />
<div
className={this.props.classes.bodyContainer}
style={{ height: this.state.height - appHeaderHeight - 70 }}>
<Grid
container
spacing={0}
alignItems={'flex-start'}
direction={'row'}
justify={'flex-start'}>
<Grid
item
sm={12}
md={6}
className={this.props.classes.leftGrid}
style={{ height: this.state.height - appHeaderHeight - 70 }}>
<Button
className={this.props.classes.saveButton}
variant="fab"
color="secondary"
aria-label="Add"
disabled={this.state.saveButtonDisabled}
onClick={this.onSaveButtonClick}>
<AddIcon />
</Button>
<AceEditor
mode="javascript"
theme="gruvbox"
width="100%"
value={this.state.editorValue}
onChange={this.onEditorChange}
height={this.state.height - appHeaderHeight - 70}
name="editor"
editorProps={{ $blockScrolling: true }}
ref={this.state.editor}
/>
</Grid>
<Grid
item
sm={12}
md={6}
className={this.props.classes.rightGrid}
style={{ height: this.state.height - appHeaderHeight - 70 }}>
<List component="nav" className={this.props.classes.navList} />
{allSnippets}
</Grid>
</Grid>
</div>
</div>
)
}
}
const App = withStyles(styles)(
connect(
mapStateToProps,
mapDispatchToProps
)(AppComponent)
)
AppComponent.propTypes = {
snippets: PropTypes.arrayOf(
PropTypes.shape({
id: PropTypes.number.isRequired,
text: PropTypes.string.isRequired
}).isRequired
).isRequired,
history: PropTypes.array,
addSnippet: PropTypes.func.isRequired
}
const store = createStore(rootReducer, composeWithDevTools())
const SnippetApp = () => (
<Provider store={store}>
<App />
</Provider>
)
export default SnippetApp
Am I mutating state in the editSnippetReducerFunction reducer or something?
Yes, you are. You are mutating the snipped that you want to update.
You probably want to do this instead:
const editSnippetReducerFunction = (state: any, action): any => ({
...state,
snippets: state.snippets.map(snippet =>
snippet.id === action.payload.id
? {...snipped, text: action.payload.text}
: snipped
)),
});
Also, notice that this:
return {snippets: newSnippets, ...state}
Is not the same as this:
return {...state, snippets: newSnippets}
With first one, if state has a property named snippets that property will be used, instead of your newSnippets. With the second one, on the other hand, the snippets property will be updated with the newSnippets.
Basically, the first one is sugar for:
return Object.assign({}, {snippets: newSnippets}, state);
While the second one is the equivalent of:
return Object.assign({}, state, {snippets: newSnippets});
In any event, the implementation of editSnippetReducerFunction that I'm suggesting addresses the 2 different problems that you had with your original implementation.
I'm making a modal that will popup when the user clicks a flatlist button or items, and there the user will see the details about the item he/she clicks. Basically, I want to pass the items of flatlist to modal.
I'm actually done with the popup of the modal, now I have to show the details like menu description and menu price. I've found a post here in stackoverflow and I follow everything in there but I am having an error regarding with an " id ", and I can't figure out how to fix it.
Here is my code
Details.js
import React, {Component} from 'react';
import {Text, TouchableHighlight, View,
StyleSheet, Platform, FlatList, AppRegistry,
TouchableOpacity, RefreshControl, Dimensions, Modal, TextInput, TouchableWithoutFeedback, Keyboard
} from 'react-native';
import AddModal from '../Modal/AddModal';
var screen = Dimensions.get('window');
const DismissKeyboard = ({ children }) => (
<TouchableWithoutFeedback onPress = {() => Keyboard.dismiss()}>
{children}
</TouchableWithoutFeedback>
);
export default class Details extends Component {
static navigationOptions = {
title: ''
};
constructor()
{
super ()
this.state = {
data: [],
showModal: false,
id: null,
}
}
fetchData = async() => {
const { params } = this.props.navigation.state;
const response_Cat = await fetch('http://192.168.254.101:3307/categories/' + params.id);
const category_Cat = await response_Cat.json();
this.setState({data: category_Cat});
};
componentDidMount() {
this.fetchData();
};
_onRefresh() {
this.setState({ refreshing: true });
this.fetchData().then(() => {
this.setState({ refreshing: false })
});
};
_onPressItem(id) {
this.setState({
modalVisible: true,
id: id
});
}
_renderItem = ({item}) => {
return (
<TouchableHighlight
id = { item.menu_desc }
onPress = { this._onPressItem(item.menu_desc) }
>
<View>
<Text>{ this.state.id }</Text>
</View>
</TouchableHighlight>
)
};
render() {
const { params } = this.props.navigation.state;
return (
<View style = { styles.container }>
<AddModal
modalVisible = { this.state.modalVisible }
setModalVisible = { (vis) => { this.setModalVisible(vis) }}
id = { this.state.id }
/>
<FlatList
data = { this.state.data }
renderItem = { this._renderItem }
keyExtractor={(item, index) => index}
/*refreshControl = {
<RefreshControl
refreshing = { this.state.refreshing }
onRefresh = { this._onRefresh.bind(this) }
/>
}*/
/>
</View>
);
}
}
const styles = StyleSheet.create({
...
})
//AppRegistry.registerComponent('Details', () => Details);
AddModal.js
import React, {Component} from 'react';
import {Text, TouchableHighlight, View,
StyleSheet, Platform, FlatList, AppRegistry,
TouchableOpacity, RefreshControl, Dimensions, TextInput, Modal
} from 'react-native';
export default class AddModal extends Component {
constructor(props) {
super(props);
this.state = {
showModal: false,
id: null
};
}
componentWillReceiveProps(nextProps) {
this.setState({
showModal: nextProps.showModal,
id: nextProps.id,
})
}
render() {
return (
<Modal
animationType="slide"
transparent={ true }
visible={ this.state.modalVisible }
onRequestClose={() => { this.props.setModalVisible(false) }}>
<View>
<View>
<Text>{ this.state.id }</Text>
<TouchableHighlight
onPress = {() => { this.props.setModalVisible(false) }}
>
<Text>Hide Modal</Text>
</TouchableHighlight>
</View>
</View>
</Modal>
)
}
}
Just wanted to pointout an issue in your code (not related to 'id' error, id error already answer by digit). In the renderItem function, you are calling onPress = { this._onPressItem(item.menu_desc) }, it should be changed to
onPress = { () => this._onPressItem(item.menu_desc) }
I guess, you will call the onPressItem when user click on list item.
EDIT:
I have made a couple of changes to make your code working. Here are the changes.
In your AppModal.js, you are setting modal visibility in showModal: nextProps.showModal , but in the <Modal ...> you have set visible
= { this.state.modalVisible }. Also in Details.js you have written <AddModal modalVisible ...>.
First I changed showModal to modalVisible in Details.js and in AppModal.js.
Details.js
constructor()
{
super ()
this.state = {
data: [],
modalVisible: false,
id: null,
}
}
Then I changed _onPressItem(id) to _onPressItem = (id)
Made changes in renderItem as
<TouchableHighlight
id = { item.enName }
onPress = { () => this._onPressItem(item.enName) }
>
in render function I have set modal visibility as
<AddModal
...
setModalVisible = { (vis) => { this.setState({
modalVisible: vis
})
}}
...
/>
AppModal.js
Changed showModal to modalVisible
constructor(props) {
super(props);
this.state = {
modalVisible: props.modalVisible,
d: null
};
}
componentWillReceiveProps(nextProps) {
this.setState({
modalVisible: nextProps.modalVisible,
id: nextProps.id,
})
}
In the constructor, I have added modalVisible: props.modalVisible.
Hope this will help!
I guess item.menu_desc is an id of each item so it must be {item.menu_desc} not {id}. Change it like below
_renderItem = ({item}) => {
return (
<TouchableHighlight
id = { item.menu_desc }
onPress = { this._onPressItem(item.menu_desc) }
>
<View>
<Text>{ item.menu_desc }</Text>
</View>
</TouchableHighlight>
)
};