React how to call a method from store and from props - javascript

I'm trying to make page pagintation in my model . I've used #material-ui TablePagination . The thing is, I'm using a web service to load my data and I don't want to store all the data inside the page, so I'm using the API paging offered (send parameters to the url for the correct page) .
Now to my code :
<TablePagination
component="div"
count={props.totalTableRows}
rowsPerPage={props.rowsPerPage}
page={props.brokersListPage}
onChangePage={props.setBrokersListPage}
rowsPerPageOptions = {[props.rowsPerPage]}
/>
And the setBrokersListPage :
export const setBrokersListPage = (event, page) => {
return dispatch => {
dispatch({
type: actionNames.SET_BROKERSLIST_PAGE,
page
})
getBrokers(page)
}
}
This code doesn't work . I need the dispatch action to refresh the state of the page , and I need the getBrokers to call the web service once again with the correct info . But all this does is update the page state without updating the data.
If I use this :
export const setBrokersListPage = (event, page) => {
return getBrokers(page)
}
Then the page refreshes , but then the state doesn'
tget refreshed .
How can I achieve both ?

You have to make an API call first, then pass this data to store, connected component will update afterwards. In your code i suppose you don't use the actual data from web service.
Here is simplified example:
Promise.resolve()
.then((page) => {
store.dispatch({
type: LOADING_BROKERS
});
return Api.getbrokers(page);
//get brokers here
})
.then(() => {
store.dispatch({
type: LOADED_DATA_BROKERS,
pageinfo // or whatever
});
})

Related

How to add my subscription data to update my previous query

I have one query and one subscription, what I am trying to do is add my data to previous query so that it shows the full list.
I have one query which is returning me list of students and I am rendering that on UI like below
function Test(props) {
const { loading, data: dta } = useQuery(GETSTUDENTS);
const { data: d } = useSubscription(GETSUBSTUDENTS, {
onSubscriptionData: ({ subscriptionData: { data } }) => {
let fname = data.getSubStudent.fname;
let lname = data.getSubStudent.lname;
dta.getStudents.push({ fname, lname });
},
});
return (
<div className="">
{dta &&
dta.getStudents.map((li) => {
<div>
<p>{li.fname}</p>
<p>{li.lname}</p>
</div>;
})}
</div>
);
}
export default Test;
But the main issue is the above one is not updating the cache so when I change the routes and come bqack again it takes the previous data only.
So What I wnat to know na what is the best way to do this, I have check subscribeToMore also but did not get idea How to implement that and how it works with hooks.
I am getting some data from subscription and on that basis I want to change some other part so can I use refetchQueries I did not found any good tutorial which uses hooks (react-apollo-hooks) using qraphql
First, you can just use the pooling option of the useQuery instead of subscription,
I suggest you check it.
From Apollo docs:
"In the majority of cases, your client should not use subscriptions to
stay up to date with your backend. Instead, you should poll
intermittently with queries, or re-execute queries on demand when a
user performs a relevant action."
Apollo subscription
If you still want to use the subscription I think you should use the subscribeToMore and to update your cache policy inside the apollo cache file:
const cache = new InMemoryCache({
typePolicies: {
Agenda: {
fields: {
tasks: {
merge(existing = [], incoming: any[]) {
return [...existing, ...incoming];
},
},
},
},
},
});
You can read more about it here: merge cahce
And check that video: youtube apollo cache

React: Reloading the page doesn't fetch the data anymore

When I am on my home page and click on a "lesson" component, the lesson page loads, takes the id of the lesson from the url and gets the data (from a local js file) to populate the lesson page. Well, that only happens when I click from the home page. But when I'm already on the lesson page with the data populated and I reload the page, I takes the id from the url but this time the data appear "undefined"... I don't understand why it doesn't take the data as previously?
Here is my component implementation:
const Lesson = () => {
const { id } = useParams();
const [lesson, setLesson] = useState(getLesson(id));
console.log("id: ", id);
console.log("lesson: ", lesson);
return (...);
};
Here is the console when I click on my lesson component from the home page:
the console when it works
There is the console when I simply reload the lesson page: the console when it doesn't work
I tried using useEffect() with a setLesson(getLesson(id)) inside but nothing changed...
I also tried this:
if (id) lesson = getLesson(id);
But again, it didn't work... :(
getLesson() gets its data from this file called fakeLessonsService.js:
import getHipHopLessons from "./hipHopLessons";
const lessons = [...getHipHopLessons()];
export function getLesson(lessonId) {
return lessons.find((lesson) => lesson._id === lessonId);
}
The file "./hipHopLessons" simply returns an array of lesson objects.
getLesson() is only loaded on this page.
The argument to useState is only used on initial render.
You should use a useEffect to update the state if the id changes
const [lesson, setLesson] = useState({});
useEffect(() => {
getLesson(id).then(val => setLesson(val));
}, [id]);
PS. Make sure getHipHopLessons is not asynchronous
If it is async, then you must write the code like
import getHipHopLessons from "./hipHopLessons";
export async function getLesson(lessonId) {
const lessons = getHipHopLessons();
return lessons.find((lesson) => lesson._id === lessonId);
}

How do I get my api call to call a different file?

I am using the api http://aws.random.cat/meow and it gives me a result of
{"file": "https://purr.objects-us-east-1.dream.io/i/rEJ7q.jpg"}
The file changes every time I refresh the api call on the browser which gives me a different cat pic. For example, if I refresh it would give me a different .jpg like
{"file": "https://purr.objects-us-east-1.dream.io/i/ferbus.jpg"}
I call the api in my React app, and I want to randomize the cat pic after an onClick of a button. Unfortunately, I get the same picture back when I do my api call. I put the file in an img src, but it doesn't change when I do another api call.
componentDidMount() {
this.getCats();
}
getCats = () => {
axios.get(`http://aws.random.cat/meow`)
.then(res => {
let cats = res.data.file;
console.log(cats)
this.setState({
cats
})
})
.catch(err => console.log(err))
}
render() {
return (
<div>
<img
src={this.state.cats}
alt='cat'
/>
<button onClick={this.getCats}>
Click me
</button>
</div>
);
}
I expect to get a different file every time, but instead I get the same .jpg when I do an onClick.

How can I pass data from Angular to Node.Js server and vice versa by one endpoint?

I have code in Nodejs as backend and Angular as frontend.
I want to receive and send data by one endpoint and based on that data from server toggle a button. Toggling is working now but I want when I sign out from the dashboard next time that I log in I could see the value of the key is based on the value from the database.
For example, first, it's SET after clicking it changed to CLEAR and I sign out from the dashboard. When next time I log in I want to see the CLEAR label on my button.
These are codes for several parts of the app:
Angular Service
this.setUserFeatured = function(id, setFeatured) {
return $http.put('/admin/v2/users/' + id + '/featured', { setFeatured: setFeatured })
.then(returnedDataOrError);
};
Angular Controller
function updateFeaturedButtonLabel() {
$scope.featuredButtonLabel = $scope.user.setFeatured ? "Clear Featured" : "Set Featured";
}
function toggleFeatured () {
$scope.user.setFeatured = !$scope.user.setFeatured;
UserService.setUserFeatured($stateParams.id, $scope.user.setFeatured)
updateFeaturedButtonLabel();
};
Html File
<a class="btn btn-info" ng-click="toggleFeatured()" ng-class="{on:user.setFeatured}">{{featuredButtonLabel}}</a>
Server Controller
function addFeaturedUser(req: $Request, res: $Response, next: NextFunction) {
const schema = Joi.object().keys(_.pick(validate, ['userId', 'setFeatured']));
const queryParams = { userId: req.params.id };
if (!req.params.id) {
return new errors.BadRequest('userId is not specified');
}
return validate.validate(queryParams, schema)
.then(validatedParams =>
userService5.updateUserLabel(validatedParams.userId, req.body.setFeatured))
.then(result => res.json(result))
.catch(next);
}
router.put('/users/:id/featured', addFeaturedUser);
And updateUserLabel is a function that handling the connection to the database and retrieving the data.
I just wonder how can I use the data from the server to change the label of the button?
true/false for the setting the button is coming from the .then(result => res.json(result))
Thanks in advance for help
For your question, I suppose you are asking how to use the response object returned in
$http.put().then(function(response){})
You can find the structure of response object in following document.
https://docs.angularjs.org/api/ng/service/$http
To access the data returned from server:
$http.put().then(function(response){response.data})
which corresponds to what your server sends.
Besides, the toggleFeatured function should be add to $scope object.
Otherwise, ng-click can't trigger that function in html template.
Hope it helps.

Send dispatch and redirect after state is updated in redux ?

I am new in front end development. Now I do study project (simple task editor, without server side) on base of reactJs+redux. I encounter with next problem.
I have some component that show web page on url '/addTask/'.
const TaskCreator = ({ tasks, onAddTask }) => {
...
const addTask = () => {
const newTask = {
id: newId,
header: headerInput.value,
description: descriptionInput.value
}
onAddTask(newTask);
}
return(
<div>
...
<button className='btn btn-success' onClick={addTask}>Save</button>
</div>
);
}
export default connect(
(state) => ({
tasks: state.tasks
}),
dispatch => ({
onAddTask: (task) => {
const payload = {
id: task.id,
header: task.header,
description: task.description
};
dispatch({ type: 'ADD_TASK', payload });
browserHistory.push('/');
}
})
)(TaskCreator);
When user click on button Save. addTask has called. After that onAddTask method faired and ADD_TASK task command disptached.
After new task has added to state there is need to redirect to url /.
When I insert statement browserHistory.push('/'), browser redirect to url / but it didn't update state with new task. If I delete statement browserHistory.push('/') like that
onAddTask: (task) => {
const payload = {
id: task.id,
header: task.header,
description: task.description
};
dispatch({ type: 'ADD_TASK', payload });
}
The state updated but browser didn't redirect.
How can I asynchronously update state (using dispatch) and after state has updated, redirect to url / ?
Thanks for advance
You should to know how treat async (like chain reaction) in react and redux.
Redux-saga helps you. https://github.com/redux-saga/redux-saga
Eventually, I found workaround of my problem.
Really, my problem was in clearing state during browser reload. And when I try to use push(/) it reload webpage so state variable cleared and can't see new (added in '/addTask/' page) tasks on '/' url.
To avoid clearing webpage there is need to go back (in browser) or manually print '/' url. I found programmatical analog for manual enter '/' url. To do this there is need to change:
<button className='btn btn-success' onClick={addTask}>Save</button>
to Link with to attribute that manual redirect:
<Link className='btn btn-success' to=`/` onClick={addTask}>Сохранить</Link>
onClick handle click (save new task) and to redirect to '/' url.
Thank you all for answers.

Categories

Resources