When i click on the document, the data successfully fetches from, however when i go to the same page and do a refresh then click on the document fetch is no longer happening ( i have inspect it in the browser ). What could be the reason for such a behavior?
this is my componentDidMount
#inject('selectedDocsStore')
#observer
class GeneralDocPresenter extends React.Component {
state = {
metaInfoDocs: [],
docs: [],
loading: false
};
componentDidMount() {
this.props.selectedDocsStore.clear();
this.props.selectedDocsStore.setViewDocId(0);
this.setState({loading: true});
this.props.fetchMetaDocs()
.then((r) => this.setState({metaInfoDocs: r.data, loading: false}))
.catch(err => {
this.setState({loading: false});
errorWithMessage('Could not load documents');
});
this.props.eventManager.on('viewDoc', (doc) => {
this.loadDocuments(doc.id);
})
}
render() {
return <Translation>
{(t) => {
if (this.state.loading) {
return (
<div style={{display: 'flex', justifyContent: 'center'}}>
<Spin size={"medium"}/>
</div>
)
}
if (this.state.metaInfoDocs.length === 0) {
return (
<div style={{display: 'flex', justifyContent: 'center'}}>
<NoDocumentsAlert><div dangerouslySetInnerHTML={{__html: t('noDocuments')}}/></NoDocumentsAlert>
</div>
)
}
return (
<DocViewWrapper docs={this.state.docs}
metaInfoDocs={this.state.metaInfoDocs.map(doc => {
return {...doc, type: this.props.type}
})}
eventManager={this.props.eventManager}
settings={this.props.settings}
childComponents={this.props.childComponents}
/>
)
}}
</Translation>
}
loadDocuments(id) {
this.props.loadDocument(id).then(r => {
this.setState({
docs: r.data
})
});
}
}
Related
I've implemented an searchbar as a header of a flatlist which displays my api data (the flatlist works fine ) but the searchbar don't work , i've tried several codes but stills not working
If someone can help me with this i'll appreciate it :)
My API displays an document which contains :
-Titre(String)
-Montant(Number)
I want to search by Titre .
Here's the last code that i've tried :
class listDépenses extends React.Component{
constructor() {
super();
this.state = {
refreshing: true,
dataSource: [],
Montant:'',
Titre:'',
modalVisible:false,
loading: false,
data: [],
error: null,
}
this.arrayholder = [];
}
renderItem = ({item}) => {
<View style={{flex:1}}>
<Text style={[globalStyles.sousTitre,{marginVertical:10,marginLeft:10}]}>{item.Titre}</Text>
<Text style={[globalStyles.sousTitre,
{marginVertical:10,marginLeft:40,textAlignVertical:'auto',opacity:0.8,fontWeight:'800'}]}>
{item.Montant}</Text>
</View>}
searchFilterFunction = text => {
const newData = this.arrayholder.filter(item => {
const itemData = `${item.Titre.toUpperCase()}`;
const textData = text.toUpperCase();
return itemData.indexOf(textData) > -1;
});
renderHeader = () => {
return(
<SearchBar
placeholder="Tapez ici..."
onChangeText={text => this.searchFilterFunction(text)}
round="default"
lightTheme="default"
/>
)
}
this.setState({ data: newData });
};
async componentDidMount() {
await fetch ('http://192.168.1.10:8080/api/depenses',{
method:'get',
mode:'no-cors',
headers:{
'Accept':'application/json',
'Content-Type':'application/json'
}})
.then((response) => response.json())
.then((responseJson) => {
this.setState({
dataSource:responseJson,
data: responseJson.results,
loading: false,
})
this.arrayholder = responseJson.results;
})
.catch((error) =>{
console.log(error)
})}
render(){
return (
<View style={{flex:1}}>
<View style={{marginBottom:10}}></View>
<FlatList
data={this.state.dataSource}
renderItem={this.renderItem}
keyExtractor={(item, index) => index}
ItemSeparatorComponent={this.renderSeparator}
ListHeaderComponent={this.renderHeader}
/>
</View>
I've found the solution if anyone need it :
class listDépenses extends React.Component{
constructor(props) {
super(props);
this.delayValue = 8000;
this.state = {
search:'',
dataSource: [],
animatedValue: new Animated.Value(0),
Montant:'',
Titre:'',
isLoading:true,
modalVisible:false,
}
this.arrayholder=[]
}
componentDidMount() {
Animated.spring(this.state.animatedValue, {
toValue: 1,
tension: 20,
useNativeDriver: true
}).start();
return fetch('http://localhost:8080/api/depenses')
.then((response )=> response.json())
.then(responseJson => {
this.setState({
dataSource: responseJson,
isLoading: false,
},
function() {
this.arrayholder = responseJson;
});})
.catch(error => { console.error(error);});}
search = text => { console.log(text);
};
clear = () => { this.search.clear();
};
SearchFilterFunction(text) {
const newData = this.arrayholder.filter(function(item) { const itemData = item.Titre
? item.Titre.toUpperCase() :
''.toUpperCase();
const textData = text.toUpperCase(); return itemData.indexOf(textData) > -1;
});
this.setState({ dataSource: newData, search: text,
});
}
render(){
if (this.state.isLoading) { return (
<View style={{ flex: 1, paddingTop: 21 }}>
<ActivityIndicator />
</View>
);
}
return (
<View style={styles.container}>
<SearchBar
round="default"
lightTheme="default"
searchIcon={{ size: 25 }}
onChangeText={text => this.SearchFilterFunction(text)} onClear={text =>
this.SearchFilterFunction('')} placeholder="Tapez ici pour chercher..." value=
{this.state.search}
/>
<View style={{marginBottom:10}}></View>
<FlatList
data={this.state.dataSource}
renderItem={this.renderItem}
keyExtractor={(item, index) => index.toString()}
enableEmptySections={true} style={{ marginTop: 11 }}
ItemSeparatorComponent={this.renderSeparator}
/>
</View>
export class Diet extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
fullData: [],
loading: false,
error: null,
query: "",
};
}
async componentDidMount() {
this.requestAPIFood();
}
requestAPIFood = _.debounce(() => {
this.setState({ loading: true });
const apiURL =
"https://api.edamam.com/api/food-database/v2/nutrients?app_id=${########}&app_key=${#######}";
fetch(apiURL)
.then((res) => res.json())
.then((resJson) => {
this.setState({
loading: false,
data: resJson,
fullData: resJson,
});
})
.catch((error) => {
this.setState({ error, loading: false });
});
}, 250);
renderFooter = () => {
if (!this.state.loading) return null;
return (
<View
style={{ paddingVertical: 20, borderTopWidth: 1, borderColor: "red" }}
>
<ActivityIndicator animating size="large" />
</View>
);
};
_renderItem = ({ item, index }) => {
return (
<TouchableOpacity style={{ height: hp("5%") }}>
<Text style={{ left: wp("1%") }}>{item.food}</Text>
</TouchableOpacity>
);
};
handleSearch = (text) => {
const data = _.filter(this.state.fullData);
this.setState({ data, query: text });
};
render() {
return (
<SearchBar
placeholder="Search Food..."
onChangeText={this.handleSearch}
value={data}
/>
<List >
<FlatList
data={this.state.data}
renderItem={this._renderItem}
keyExtractor={(item, index) => index.toString()}
ListFooterComponent={this.renderFooter}
/>
</List>
Good evening, I'm working on a SearchBar component to search food from the API database of Edamam (this is the link to the documentation: https://developer.edamam.com/food-database-api-docs) and display the result on a FlatList as you can see above, but when I start typing nothing will appear and I really can't seem to find the error.
I am working on react app which uses redux for state management. In this app i have to implement search page. In which when user types on search box the app display the product related to that text input.
I have api endpoint like this api.XXXXXXX.com/buyer/product/filter?q=${inputValue}. I tried implement this but i am not able filter this. I haven't worked on this before and couldn't find good tutorial for this.
Here is my code
searchAction.js
export const searchProduct =(value) => dispatch => {
dispatch({
type: searchActionTypes.SEARCH_PRODUCT_LOAD
});
new _rest().get(`/buyer/product/filter?q=${value}`)
.then(res => {
console.log(res);
dispatch({
type: searchActionTypes.SEARCH_PRODUCT_SUCCESS,
payload: res
})
}).catch(err => {
console.log(err)
dispatch({
type: searchActionTypes.SEARCH_PRODUCT_ERROR,
error: err
})
});
}
searchActionreducer.js
const initialState = {
isFetching: false,
searchData: {},
isFetched: false,
isError: null
}
export default (state=initialState, action) =>{
switch (action.type) {
case searchActionTypes.SEARCH_PRODUCT_LOAD:
return {
...state,
isFetching: true
};
case searchActionTypes.SEARCH_PRODUCT_SUCCESS:
return {
...state,
isFetching: false,
searchData: action.payload.data._embedded,
isFetched: true
};
case searchActionTypes.SEARCH_PRODUCT_ERROR:
return {
...state,
isFetched: false,
};
default:
return {
...state
}
}
}
searchPage.js
class SearchPage extends React.Component {
state = {
inputValue: '',
}
componentDidMount() {
this.props.searchProduct('');
}
componentDidUpdate(prevProps, prevState, snapshot) {
console.log('component update', prevState)
if(this.state.inputValue !== prevState.inputValue) {
this.props.searchProduct(this.state.inputValue);
}
}
render() {
console.log('SearchPage Result', this.props.product);
const {product} = this.props;
const {inputValue} =this.state;
const updateInputValue = (e) => {
e.preventDefault();
this.setState({
inputValue: e.target.value
})
}
return(
<Grid container>
<div style={{width: '100%', display:'flex', justifyContent: 'center' }}>
<form noValidate autoComplete="off">
<TextField value={inputValue} onChange={updateInputValue} id="standard-basic" label="Search Product" />
</form>
</div>
<Grid container spacing={8} style={{padding: '30px'}}>
{product && product.productResourceList &&
product.productResourceList.map((data, index) => {
return(
<Grid item xs={6}>
<MainCards key={data.productId} data={data} />
</Grid>
)
})}
</Grid>
</Grid>
)
}
}
const mapStateToProps =(state) => {
return {
product: state.search.searchData
}
}
const mapDispatchToProps = {
searchProduct,
}
export default connect(mapStateToProps, mapDispatchToProps)(SearchPage);
Here In componentDidMount Initially when component mounts i made display all the product. After that in componentDidUpdate i trying get filtered data from api buy passing this.state.inputValue as value of q in api endpoint api.XXXXXXX.com/buyer/product/filter?q=${inputValue}. But component is not updating at all.
I'm working on React native. I'm using FlatList. I want to show the loading bar as I go down. I wrote the code for that.
I've reviewed the documentation, but it's not working. I guess I'm making a mistake at the await. I don't know how to use it. What is the difference of async? I'm leaving the code sample below.
Thanks in advance for your help.
handleRefresh = () => {
this.setState({
offset: 0,
maxSize: 10,
isSearch: false,
isLoading: true,
isRefreshing: true
}, () => {
this.loadData();
});
};
handleLoadMore = () => {
this.setState({
maxSize: this.state.maxSize + 5,
isSpinner: true
}, () => {
this.loadData();
});
};
keyExtractor = (item, index) => index.toString();
renderFooter = () => {
if(this.state.isSpinner === false) { return null; }
return (
<View style={{ paddingVertical: 20 }}>
<ActivityIndicator animating size="small" />
</View>
);
};
loadData = async () => {
try {
const { offset, maxSize } = this.state;
const username = await AsyncStorage.getItem('username');
const token = await AsyncStorage.getItem('token');
var credentials = Base64.btoa(username + ':' + token);
var URL = `http://demo.espocrm.com/advanced/api/v1/Lead?sortBy=createdAt&asc&offset=${offset}&maxSize=${maxSize}`;
axios.get(URL, {headers : { 'Espo-Authorization' : credentials }})
.then(this.dataSuccess.bind(this))
.catch(this.dataFail.bind(this));
} catch (error) {
Alert.alert(
'Hata',
'Bir hata meydana geldi. Lütfen yöneticiye başvurunuz.',
[
{ text: 'Tamam', onPress: () => null }
]
);
}
};
dataSuccess(response) {
this.setState({ isRefreshing: false, isSpinner: false, isLoading: false, leadList: response.data.list });
}
dataFail(error) {
this.setState({ isLoading: false });
Alert.alert(
'Hata',
'Beklenmedik bir hata oluştu',
[
{ text: 'Tamam', onPress: () => null }
]
);
}
render() {
const { isLoading, isRefreshing, searchText, leadList } = this.state;
return(
<View style={styles.container}>
<SearchBar
placeholder="Bir lead arayın..."
onChangeText={this.searchLead.bind(this)}
onClear={this.handleRefresh}
onCancel={this.loadData}
value={searchText}
/>
{
isLoading ? <ActivityIndicator style={styles.loading} size="large" color="orange" /> :
<FlatList
data={leadList}
ListFooterComponent={this.renderFooter}
renderItem={({item}) =>
<ListItem
leftAvatar={{ source: { uri: 'https://pbs.twimg.com/profile_images/567081964402790401/p7WTZ0Ef_400x400.png' } }}
title={item.name}
subtitle={item.status}
bottomDivider={true}
/>
}
keyExtractor={this.keyExtractor}
refreshing={isRefreshing}
onRefresh={this.handleRefresh}
onEndReached={this.handleLoadMore}
onEndReachedThreshold={0.5}
/>
}
</View>
)
}
}
In your FlatList component, you need to include an attribute called extraData and set that to this.state so the component will update.
<FlatList
data={leadList}
extraData={this.state}
...
/>
I want to get dynamic content with React js modal I am using package react-responsive-modal. First I render all the post through map. Now I want when I click the individual post the modal should pop up and show me only that particular post's title and body. Now I can't figure out how to get an individual post in modal.
Is it possible to do that via third-party package or I have to make custom modal for that?
import React from 'react';
import Modal from 'react-responsive-modal';
import Axios from 'axios';
const styles = {
fontFamily: 'sans-serif',
textAlign: 'center'
};
class App extends React.Component {
state = {
posts: [],
open: false
};
componentDidMount() {
let url = 'https://jsonplaceholder.typicode.com/posts';
Axios.get(url).then(res => {
this.setState({
posts: res.data.slice(0, 10)
});
console.log(res.data.slice(0, 10));
});
}
onOpenModal = () => {
this.setState({ open: true });
};
onCloseModal = () => {
this.setState({ open: false });
};
renderPosts() {
return this.state.posts.map(post => {
return (
<div
key={post.id}
style={{ width: 400, height: 400, backgroundColor: 'orange' }}
onClick={this.onOpenModal}
>
<h1>{post.title}</h1>
</div>
);
});
}
renderModal(id, title, body) {
return this.state.posts.map(post => {
return (
<div key={post.id} style={{ width: 400, height: 400, backgroundColor: 'orange' }}>
<h1>{post.id}</h1>
<h1>{post.title}</h1>
<p>{post.body}</p>
</div>
);
});
}
render() {
const { open } = this.state;
return (
<div style={styles}>
<h2>react-responsive-modal</h2>
<div>{this.renderPosts()}</div>
<Modal open={open} onClose={this.onCloseModal} center>
<h2>Simple centered modal</h2>
<div>{this.renderModal()}</div>
</Modal>
</div>
);
}
}
export default App;
You'll need to introduce some additional state on your App component that keeps track of the currently selected post. In your onOpenModal() method, you can update that state with the index of the post that was clicked. Then, in renderModal(), you can check what the selected post is and only render that post instead of mapping over the entire array.
class App extends React.Component {
state = {
posts: [],
open: false,
selectedPost: null // Keep track of the selected post
};
componentDidMount() {
let url = "https://jsonplaceholder.typicode.com/posts";
Axios.get(url).then(res => {
this.setState({
posts: res.data.slice(0, 10)
});
console.log(res.data.slice(0, 10));
});
}
onOpenModal = i => {
this.setState({
open: true,
selectedPost: i // When a post is clicked, mark it as selected
});
};
onCloseModal = () => {
this.setState({ open: false });
};
renderPosts = () => {
return this.state.posts.map((post, i) => {
return (
<div
key={post.id}
style={{ width: 400, height: 400, backgroundColor: "orange" }}
onClick={() => this.onOpenModal(i)} // Pass the id of the clicked post
>
<h1>{post.title}</h1>
</div>
);
});
}
renderModal = () => {
// Check to see if there's a selected post. If so, render it.
if (this.state.selectedPost !== null) {
const post = this.state.posts[this.state.selectedPost];
return (
<div
style={{ width: 400, height: 400, backgroundColor: "orange" }}
>
<h1>{post.id}</h1>
<h1>{post.title}</h1>
<p>{post.body}</p>
</div>
);
}
}
render() {
const { open } = this.state;
return (
<div style={styles}>
<h2>react-responsive-modal</h2>
<div>{this.renderPosts()}</div>
<Modal open={open} onClose={this.onCloseModal} center>
<h2>Simple centered modal</h2>
<div>{this.renderModal()}</div>
</Modal>
</div>
);
}
}
In the post onClick function set the post id/index in state along with the open flag
Inside the modal render use the saved index/id to pass that post to the modal as a param/prop.
You dont need to map over all posts inside the modal.
Sample
onOpenModal = (index) => {
this.setState({ open: true, selectedPostIndex: index });
};
onCloseModal = () => {
this.setState({ open: false, selectedPostIndex: undefined })
}
renderPosts() {
return this.state.posts.map((post, index) => {
return (
<div key={post.id} onClick={() => this.onOpenModal(index)}>
<h1>{post.title}</h1>
</div>
)
})
}
render() {
....
<Modal open={open} onClose={this.onCloseModal} center>
<h2>Simple centered modal</h2>
<div>{this.renderModal(this.state.posts[this.state.selectedPostIndex])}</div>
</Modal>
....
}
renderModal(post) {
return (
<div key={post.id} style={{ width: 400, height: 400, backgroundColor: 'orange' }}>
<h1>{post.id}</h1>
<h1>{post.title}</h1>
<p>{post.body}</p>
</div>
)
}
Using React Hooks
Create a modal with dynamic props like this
export default function Modal({
open,
setOpen,
onConfirm,
title,
description,
confirmText,
})
Then render the component.
i did it like this
const getModal = () => {
return (
<Modal open={open} setOpen={setOpen} title={title} description={description} confirmText={confirmText} onConfirm={confirmAction} />
)
}
and then when you want to display your dynamic modal
use a function like this
ConfirmAction can not be a function you should call the function inside that Modal according to that confirmation
const createModal = (title, description, confirmText, confirmAction) => {
setTitle(title);
setDescription(description);
setConfirmText(confirmText);
setConfirmAction(confirmAction);
setOpen(true);
}
Initialize your state with one array which will hold
state = {
posts: [],
open: false,
modalShow: [false,false,false,false,false,false,false,false,false,false] // this is 10 as you have only 10 posts
};
Now modify render posts
onOpenModal = (id) => {
const newModalShow = [...this.state.modalShow];
newModalShow[id] = true;
this.setState({ modalShow: newModalShow});
};
renderPosts() {
return this.state.posts.map((post,index) => {
return (
<Fragement>
<div
key={post.id}
style={{ width: 400, height: 400, backgroundColor: 'orange' }}
onClick={()=>this.onOpenModal(index)}
>
<h1>{post.title}</h1>
</div>
<Modal open={this.state.modalShow[index]} onClose={this.onCloseModal} center>
<h2>post.title</h2>
<div>{this.renderModal()}</div>
</Modal>
<Fragement>
);
});
}