I've read many examples about this and got no result for my problem, I want to get the values inside MySQL database by using localhost, code with PHP and return the value as JSON format e.g.
[
{"id":"7",
"name":"Sammy",
"address":"New York",
"age":"42"}
]
with this format, I can fetch the data by using this code in GetApi.js
class GetApi {
static getAllUsers() {
return fetch('http://192.168.1.199/App/show_all_data.php')
.then((response) => {
if (!response.ok) {
throw Error(response.statusText);
}
dispatch(itemsIsLoading(false));
return response;
})
.then((response) => response.json())
.then((items) => dispatch(itemsFetchDataSuccess(items)))
.catch(() => dispatch(itemsHasErrored(true)));
}
}
export default GetApi;
here's the action.js
import GetApi from '../../api/GetApi';
export function itemsHasErrored(bool: boolean) {
return {
type: "ITEMS_HAS_ERRORED",
hasErrored: bool
};
}
export function itemsIsLoading(bool: boolean) {
return {
type: "ITEMS_IS_LOADING",
isLoading: bool
};
}
export function itemsFetchDataSuccess(items: Object) {
return {
type: "ITEMS_FETCH_DATA_SUCCESS",
items
};
}
export function itemsFetchData(url: any) {
return function(dispatch) {
return GetApi.getAllUsers().then(items => {
dispatch(itemsFetchDataSuccess(items));
dispatch(itemsIsLoading(false));
}).catch(error => {
throw(error);
});
};
}
here's the reducer.js
const initialState = {
isLoading: true,
hasErrored: false,
items: []
};
export default function(state: any = initialState, action: Function) {
switch (action.type) {
case "ITEMS_HAS_ERRORED":
return { ...state, hasErrored: action.hasErrored };
case "ITEMS_IS_LOADING":
return { ...state, isLoading: action.isLoading };
case "ITEMS_FETCH_DATA_SUCCESS":
return { ...state, items: action.items };
default:
return state;
}
}
called action.js function in index.js
import { itemsFetchData } from "../../actions";
...
all codings that were not related with calling action.js
...
const navigation = this.props.navigation;
let items = this.props.items;
if (items.hasOwnProperty('item')) {
items = items.item
}
return (
<List
dataArray={this.props.items}
renderRow={(
data
) =>
<ListItem icon style={styles.listitem}>
<Left>
<Text>
{data.name}
</Text>
</Left>
<Right>
<Text>
{data.address}
</Text>
</Right>
</ListItem>}
/>
);
function bindAction(dispatch) {
return {
fetchData: url => dispatch(itemsFetchData(url))
};
}
const mapStateToProps = state => ({
items: state.homeReducer.items,
hasErrored: state.homeReducer.hasErrored,
isLoading: state.homeReducer.isLoading
});
export default connect(mapStateToProps, bindAction)(ShowData);
I got no results when I'm running the code, it's just showed the loading icon. even when I set isLoading:false, the home menu showed up without the data
I'm just trying to minimize the code inside index.js because it's too long to post that here. I will do that if necessary in the next comment.
I recommend using epics , below is an example link for you to follow.
Epic Example
You can look at the actions and data ajax calls from epic and how it connects back to the action.
Note: Axios is been used here instead of fetch api...
Related
I've been trying to create this search app where I can display the items in a table and delete items using react redux. However, on the initial load, the app shows a table but there is no data in the table. It's an empty table. If i search for another movie name which have more than one movie for that search term, then 2 tables would be shown but I want to show everything on the same table itself. The delete button is not working as well. Is there something wrong with my action and reducer files?
Action.js
import {
FETCH_MOVIE_PENDING,
FETCH_MOVIE_SUCCESS,
FETCH_MOVIE_ERROR,
DELETE_MOVIE
} from "./types";
const fetchMoviePendig = () => ({
type: FETCH_MOVIE_PENDING
});
const fetchMovieSuccess = json => ({
type: FETCH_MOVIE_SUCCESS,
payload: json
});
const fetchMovieError = error => ({
type: FETCH_MOVIE_ERROR,
payload: error
});
export const fetchMovie = name => {
return async dispatch => {
dispatch(fetchMoviePendig());
try {
const url = `https://jsonmock.hackerrank.com/api/movies/search/?Title=${name}`;
const response = await fetch(url);
const result = await response.json(response);
console.log(result);
dispatch(fetchMovieSuccess(result.data));
} catch (error) {
dispatch(fetchMovieError(error));
}
};
};
export const deleteEvent = id => async dispatch => {
try {
dispatch({
type: DELETE_MOVIE,
payload: id
});
} catch (err) {
console.log(err);
}
};
Reducer
import {
FETCH_MOVIE_PENDING,
FETCH_MOVIE_SUCCESS,
FETCH_MOVIE_ERROR,
DELETE_MOVIE
} from "../action/types";
const initialState = {
data: [],
loading: false,
error: ""
};
const moviesReducer = (state = initialState, action) => {
switch (action.type) {
case FETCH_MOVIE_PENDING:
return {
...state,
loading: true
};
case FETCH_MOVIE_SUCCESS:
return {
...state,
loading: false,
data: [...state.data, action.payload]
};
case FETCH_MOVIE_ERROR:
return {
...state,
loading: false,
error: action.payload
};
case DELETE_MOVIE:
return {
...state,
data: state.data.filter(movie => movie.id !== action.payload)
};
default:
return state;
}
};
export default moviesReducer;
App.js
import React, { Component } from "react";
import { connect } from "react-redux";
import { fetchMovie } from "./action/movieActions";
import Input from "./components/Input";
import MovieTable from "./components/MovieTable";
class App extends Component {
state = {
searchInput: "The Rain"
};
componentDidMount() {
this.props.getMovieList(this.state.searchInput);
}
_getMovie = () => {
this.props.getMovieList(this.state.searchInput);
};
_onChangeHandler = e => {
this.setState({
searchInput: e.target.value
});
console.log(this.state.searchInput);
};
render() {
const { data, loading } = this.props.movies;
return (
<div className="center">
<div>
<h2 className="center white-text">Movie Search</h2>
</div>
<div className="container">
<Input
value={this.state.searchInput}
onChange={this._onChangeHandler}
onClick={this._getMovie}
/>
<div className="row">
{loading ? (
<p>Loading</p>
) : (
data.map(item => (
<MovieTable
key={item.imdbID}
year={item.Year}
name={item.Title}
movieId={item.imdbId}
/>
))
)}
</div>
</div>
</div>
);
}
}
const mapStateToProps = state => {
return {
movies: state.movies
};
};
const mapDispatchToProps = dispatch => {
return {
getMovieList: name => dispatch(fetchMovie(name))
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(App);
Hello please take a look at the sandbox : https://codesandbox.io/s/prod-wind-4hgq2?file=/src/App.js
I have edited
<MovieTable
data={data.map(d => ({
year: d.Year,
name: d.Title,
movieId: d.imdbId
}))}
/>
and
case FETCH_MOVIE_SUCCESS:
return {
...state,
loading: false,
data: action.payload
};
And ... Currently the delete button has no event, that's why it can't work
I see data having the following pattern:
Object {page: 1, per_page: 10, total: 1, total_pages: 1, data: Array[1]}
page: 1
per_page: 10
total: 1
total_pages: 1
data: Array[1]
0: Object
Title: "Sin in the Rain"
Year: 2006
imdbID: "tt1072449"
And you are accessing wrong properties in the component render logic, can you fix that.
Duplicate table is created the way you have written the logic.
Pass the data to MovieTable component and let it render and create the table
and fill it.
In reducer (FETCH_MOVIE_SUCCESS) you need don't need to append data you have to
replace or use the current movie data only.
I'm having trouble fetching a list of users from an api. I think issue might be in my mapDispatchToProps function but I'm not sure. Everything else seems fine to me. I'm new to redux and I'm kinda having a hard time wrapping my head around it so any help is appreciated
The list with the users would ideally be displayed as soon as the component mounts. I did the same thing without redux store and it was working just fine, I'm just not really sure how to integrate redux
Actions
export const startLoading = () => {
return {
type: START_LOADING
}
}
export const updateUserData = payload => {
return {
type: UPDATE_USER_DATA,
payload
}
}
export const updateUserError = payload => {
return {
type: UPDATE_USER_ERROR,
payload: payload
}
}
export function fetchUsers() {
return dispatch => {
dispatch(startLoading());
fetch('https://jsonplaceholder.typicode.com/users')
.then(res => res.json())
.then(data => {
data = data.filter(user => user.id < 4);
data.forEach(user => {
user.isGoldClient = false;
user.salary = '4000';
user.photo = userThumbnail;
})
.then(data => {
dispatch(updateUserData(data));
}).catch(error => {
dispatch(updateUserError(error));
})
});
};
};
Reducers
const initialState = {
loading: false,
users: [],
error: null
};
export function userReducer(state=initialState, action){
switch(action.type){
case START_LOADING:
return {
...state,
loading: true
}
case UPDATE_USER_DATA:
return {
...state,
loading: false,
users: action.payload,
error: null
}
case UPDATE_USER_ERROR:
return {
...state,
error: action.payload,
loading: false,
users: []
};
default:
return state;
};
};
Component
class Home extends React.Component {
constructor(props) {
super(props);
this.state = {
users: [],
usersAreDisplayed: true
};
}
componentDidMount() {
fetchUsers();
}
render(){
return (
<UserList users={this.state.users} />
)
}
}
function mapStateToProps(state){
return { users: state.users }
}
function mapDispatchToProps(dispatch){
return {
fetchUsers: payload => dispatch(updateUserData(payload)),
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Home);
Looks like you are not calling the actual fetchUsers at all.
Change the component code like this
function mapStateToProps(state){
return { users: state.users }
}
// remove this function
// function mapDispatchToProps(dispatch){
// return {
// fetchUsers: payload => dispatch(updateUserData(payload)),
// }
// }
export default connect(mapStateToProps, {fetchUsers})(Home); //<---- destructure it here. Also import the function (action)
1a. fetchUsers function needs to be accessed using this.props
componentDidMount() {
this.props.fetchUsers();
}
There is an extra then block after forEach.
Remove it.
export function fetchUsers() {
return (dispatch) => {
dispatch(startLoading());
fetch("https://jsonplaceholder.typicode.com/users")
.then((res) => res.json())
.then((data) => {
data = data.filter((user) => user.id < 4);
data.forEach((user) => {
user.isGoldClient = false;
user.salary = "4000";
user.photo = userThumbnail;
});
dispatch(updateUserData(data)); // <------ no extra .then is required
})
.catch((error) => {
dispatch(updateUserError(error));
});
};
}
Also <UserList users={this.state.users} /> needs to be <UserList users={this.props.users} /> As already mentioned by #Nsevens
You are mapping redux state into your component's props.
So you should load the users from the component's props and not it's state:
render(){
return (
<UserList users={this.props.users} />
)
}
There have been quite a few similar questions raised here but I couldn't find the answer to my problem.
Here is my React component:
class MyTransitPage extends Component {
componentDidMount() {
this.props.getPassengerProfile();
}
render() {
return (
<View>
<Text>{this.props.passenger.pid}</Text>
</View>
);
}
}
const mapStateToProps = ( state ) => {
return {
passenger: state.transit.passenger
}
}
export default connect(mapStateToProps, { getPassengerProfile })(MyTransitPage)
Here is my reducer:
const initialState = {
passenger: {}
};
export default(state = initialState, action) => {
console.log("reducer ");
console.log(action.payload);
switch(action.type) {
case 'GET_PASSENGER_PROFILE':
return { ...state, passenger: action.payload};
default:
return state;
}
}
When I do console.log in the reducer I can see that the payload is there:
"passenger": Object {
[20:57:55] "createdAt": "2019-02-10T13:02:40.897Z",
[20:57:55] "objectId": "YKzeH2Nh3C",
[20:57:55] "pid": "iwKHqfCQSu",
[20:57:55] "updatedAt": "2019-02-10T13:02:40.897Z",
[20:57:55] },
But when I try to access {this.props.passenger.pid} in the component, I get pid as undefined. I can't find where the problem is. Where did I get it wrong?
EDIT:
Root reducer:
export default combineReducers({
auth: AuthenticationReducer,
transit: TransitReducer
});
EDIT2: Action:
export const getPassengerProfile = () => {
const currentUser = Parse.User.current();
const currentUserId = currentUser._getId()
const Passenger = Parse.Object.extend('Passenger');
const query = new Parse.Query(Passenger);
query.equalTo("pid", currentUserId);
return (dispatch) => {
query.first().then(response => {
dispatch ({
type: 'GET_PASSENGER_PROFILE',
payload: response
});
});
};
}
You are calling this.props.getPassengerProfile() in the componentDidMount which means the component is already mounted and rendered before the state is populated from that value. I would just add a check in your render so it doesn't error out and then when it does get there it should show properly. Like this:
render() {
//console.log(this.props.transit);
console.log(this.props);
return (
<View>
<Text>{this.props.passenger ? this.props.passenger.pid : ''}</Text>
</View>
);
}
I used JSON.parse(JSON.stringify()) on the action.payload, which seems to have resolved the issue.
I'm fairly new to React Native and Redux and was following along with this tutorial to implement Redux with my app. When I load my PostList component, I get the following warnings for my hasError and isLoading catches as shown in the following screenshots.
I apologize for the massive amounts of source code about to be embedded in the question, I tried to cut out unnecessary code.
PostList.js (Component)
[unnecessary import statements]
import { fetchPosts, postsFetchError, postsFetchLoading } from '../actions/PostsActions';
class PostList extends Component {
static navigationOptions = ({navigation}) => {
[redacted]
}
renderPosts = ({ _id, upvotes, downvotes, message, datetime }, i) => {
[redacted]
}
componentDidMount() {
this.props.fetchData('[redacted]');
}
render() {
if (this.props.hasError) {
return (
<View style={styles.center}>
<Text>
Failed to load posts!
</Text>
</View>
)
}
if (this.props.isLoading) {
return (
<View style={styles.center}>
<ActivityIndicator animating={true} />
</View>
)
}
this.props.posts.sort(function(a,b) {
return Date.parse(b.datetime) - Date.parse(a.datetime);
})
return (
<ScrollView style={styles.container}>
{this.props.posts.map(this.renderPosts)}
</ScrollView>
)
}
}
PostList.propTypes = {
fetchData: PropTypes.func.isRequired,
posts: PropTypes.array.isRequired,
hasError: PropTypes.bool.isRequired,
isLoading: PropTypes.bool.isRequired
};
const mapStateToProps = (state) => {
return {
posts: state.posts,
hasError: state.postsFetchError,
isLoading: state.postsFetchLoading
};
};
const mapDispatchToProps = (dispatch) => {
return {
fetchData: (url) => dispatch(fetchPosts(url)),
};
};
export default connect(mapStateToProps, mapDispatchToProps)(PostList);
PostsActions.js
import axios from 'axios';
export function postsFetchError(bool) {
return {
type: 'POSTS_FETCH_ERROR',
hasError: bool
};
}
export function postsFetchLoading(bool) {
return {
type: 'POSTS_FETCH_LOADING',
isLoading: bool
};
}
export function postsFetchSuccess(posts) {
return {
type: 'POSTS_FETCH_SUCCESS',
posts
};
}
export function fetchPosts(url) {
return (dispatch) => {
dispatch(postsFetchLoading(true));
axios.get(url)
.then((response) => {
if (response.status !== 200) {
throw Error(response.statusText);
}
dispatch(postsFetchLoading(false));
return response;
})
.then((response) => dispatch(postsFetchSuccess(response.data)))
.catch(() => dispatch(postsFetchError(true)));
};
}
PostsReducers.js
export function postsError(state = false, action) {
switch (action.type) {
case 'POSTS_FETCH_ERROR':
return action.hasError;
default:
return state;
}
}
export function postsLoading(state = false, action) {
switch (action.type) {
case 'POSTS_FETCH_LOADING':
return action.isLoading;
default:
return state;
}
}
export function posts(state = [], action) {
switch (action.type) {
case 'POSTS_FETCH_SUCCESS':
return action.posts;
default:
return state;
}
}
Combining the reducers in an index and configuring the store all work fine, and I don't get warnings for actions and reducers that actually get the posts. My code matches the tutorial's examples, but I'd be shocked if someone published a tutorial that had unresolved warnings (then again this IS Javascript development so I guess anything goes). I can add further information for anyone that's curious. Thanks to anyone that helps.
Is it because:
const mapStateToProps = (state) => {
return {
posts: state.posts,
hasError: state.**postsFetchError**,
isLoading: state.**postsFetchLoading**
};
};
Does not match:
export function **postsError**(state = false, action) {
export function **postsLoading**(state = false, action)
How can I fetch only one data and write it to Header ?
I am using firebase and react-redux.
firebase structure i try to write "organization": inovanka:
Action File Codes:
import firebase from 'firebase';
import { Actions } from 'react-native-router-flux';
import { ORGANIZATION_NAME_DATA_SUCCESS } from './types';
export const organizationName = () => {
const { currentUser } = firebase.auth();
return (dispatch) => {
firebase.database().ref(`/organizations/${currentUser.uid}`)
.on('value', snapshot => {
dispatch({ type: ORGANIZATION_NAME_DATA_SUCCESS, payload: snapshot.val() });
});
};
}
Reducer File :
import { ORGANIZATION_NAME_DATA_SUCCESS } from '../actions/types';
const INITIAL_STATE = {
};
export default (state = INITIAL_STATE, action) => {
switch (action.type) {
case ORGANIZATION_NAME_DATA_SUCCESS:
console.log(action); // data retrieved as array
return action.payload
default:
return state;
}
};
Component: (I would like to write it to this)
class HomePage extends Component {
componentWillMount() {
}
render() {
return (
<Container>
<Header>
<Text> i would like to write it here </Text>
</Header>
<Content>
</Content>
</Container>
);
}
}
const mapStateToProps = ({ homepageResponse }) => {
const organizationArray = _.map(homepageResponse, (val, uid) => {
return { ...val, uid }; //
});
return { organizationArray };
};
export default connect(mapStateToProps, { organizationName })(HomePage);
Change this:
firebase.database().ref(`/organizations/${currentUser.uid}`)
.on('value', snapshot => {
to this:
firebase.database().ref(`/organizations/${currentUser.uid}`)
.once('value', snapshot => {
using once() will read data only one time, thus fetching only one data
Solution is Here !
Action File:
export const organizationName = () => {
const { currentUser } = firebase.auth();
return (dispatch) => {
firebase.database().ref(`/organizations/${currentUser.uid}`)
.once('value', snapshot => {
_.mapValues(snapshot.val(), o => {
console.log(o);
dispatch({ type: ORGANIZATION_NAME_DATA_SUCCESS, payload: {organization: o.organization, fullname: o.fullname }});
});
});
};
}
Reducer File
const INITIAL_STATE = {
organization: '',
};
export default (state = INITIAL_STATE, action) => {
switch (action.type) {
case ORGANIZATION_NAME_DATA_SUCCESS:
console.log(action);
return {...state, organization:action.payload.organization };
default:
return state;
}
};
Component File MapToStateProps and componentWillMount
const mapStateToProps = state => {
const { organization, fullname } = state.homepageResponse;
console.log("burada" + organization);
return { organization, fullname };
};
componentWillMount(){
this.props.organizationName();
}
*Last Step Header *
render() {
return (
<Container>
<Header>
<Text> { this.props.organization } </Text>
</Header>
</Container>
}
Thank You Everyone