<Query query={getArticlesQuery} pollInterval={0} notifyOnNetworkStatusChange={true}>
{
({ data, networkStatus, error, loading, refetch }) => {
if (networkStatus === 4) { return <Reloading /> }
if (loading) { return <Loading /> }
if (error) { return <Error /> }
//Received required data from query response
const articles = data.articles;
return (
<div onScroll={(e)=>{console.log("test")}}>
<div className="refetchbutton">
<button onClick={() => { refetch() }}>Refetch!</button>
</div>
<AllPosts allArticles={articles} onScroll={(e)=>{console.log("test")}}/>
</div>
)
}
}
</Query>
Allposts.js
class AllPosts extends React.Component{
render(){
let articles_p = this.props.allArticles;
return(
articles_p.map((article) => { return <Post key={article.id} data={article} /> })
);
}
}
I have an Apollo query component which receives data as a response.
This response is passed to another component called "AllPosts" which returns an array of the component "Post". However, they are around 122articles and in the middle section of the image attached with the post i have to scroll continuously till the last post. I want to use onScroll to notify when i am scrolling on an element. The code i have currently doesn't seem to be working, does anyone have any ideas why?
Related
I am super new to React and have just started my journey with it I have another page where I use the same function of handleIndexEmployees and the same const variables with useState and useEffect which load just fine. Right now with the code I have the only thing that shows up is
<h1>Employees</h1>
import { useState, useEffect } from "react";
import axios from "axios";
import { EmployeesAxios } from "./EmployeesAxios";
export function EmployeesIndex() {
const [employees, setEmployees] = useState([]);
const handleIndexEmployees = () => {
console.log("Wait I'm getting Da Minions");
axios.get("http://localhost:3000/employees.json").then((response) => {
console.log("Hello my Minions");
console.log(response.data);
setEmployees(response.data);
});
};
useEffect(handleIndexEmployees, []);
return (
<div>
<EmployeesAxios employee={employees} />
</div>
);
}
export function EmployeesAxios(props) {
return (
<div>
<h1>Employees</h1>
{props.employee.map((employee) => {
<div key={employee.id}>
<h3>Name: {` ${employee.first_name} ${employee.last_name}`}</h3>
</div>;
})}
</div>
);
}
{props.todos.map((todo) => (
<div key={todo.id}>
<h2>{todo.name}</h2>
<p>{todo.description}</p>
<button
onClick={() => {
axios.patch(`http://localhost:3000/todos/${todo.id}.json`).then((response) => {
console.log(response);
});
}}
>
{todo.done}
Done
</button>
<button onClick={() => props.onShowTodo(todo)}>More info</button>
</div>
))}
I tried putting this all on one page with making all the requests on that page, and I get the same response with that so my page that I am rendering for a selector wheel to assign tasks to that employee works just fine with using props so that is why I tried moving all the axios requests to another page and passing in props. I also tried using isLoading as well and this didn't work either.
It looks like you are not returning anything from your map.
Add a return statement here
{
props.employee.map((employee) => {
// Return something from the map
return (
<div key={employee.id}>
<h3>Name: {` ${employee.first_name} ${employee.last_name}`}</h3>
</div>
);
});
}
How to redirect to a 404 component if i do not receive any data from axios fetch after using the useFetch
function EditUser() {
const { id } = useParams();
const [userFound, setUserFound] = useState(false);
useEffect(() => {
try {
axios.get(`/api/user/${id}`).then((response) => {
if (response.data.length > 0) {
console.log(response);
setUserFound(true);
}
});
} catch (error) {
console.log(error);
}
}, []);
if (!userFound) {
<Redirect to="/home" />; // not working even that the state is false
}
return (
<div>
<h1>{id}</h1>
</div>
);
}
try using:
window.location.assign("/home");
the path is relative meaning that if you are in www.mypage.com/edit and want to go to www.mypage.com/home you would have to write
window.location.assign("../home");
Alternatenely I would just avoid mixing html in js meaning I would approach it like this
return (
<>
userfound ?
<div>
<h1>{id}</h1>
</div>
: <Redirect to="/home" />
</>
);
something among these lines should work
Or a while back I used this approach:
<Route path="/users" component={userfound ? CurrentPage: RedirectPage} />
where CurrentPage would contain ... and redirect your html redirect request. I' ve only used it in Route but I guess it exists in other elements as well
I am rendering a component that display an array and I want them to be order by the last entry.
I've tried to do a function outside the render that orderBy and include it in the component but it's not mounting correctly.
orderBy() {
let data = this.state;
data.data.sort((a, b) => {
return a.published_on - b.published_on
}).map((data) => {
return data;
})
}
render() {
const { loading, data } = this.state;
return (
<div className="list">
<Table rowKey="ref" loading={loading} dataSource={data.data} size="large" />
</div>
);
}
I want the Table component to be order on the loading by data.data.published_on.
What is the correct way to do that in React ?
1) You're not returning anything from the function.
2) Since you're using class components you'll need to call it with this.orderBy
3) Instead of grabbing data from the state pass it into the function instead:
orderBy(data) {
return data.sort((a, b) => a.published_on - b.published_on);
}
render() {
const { loading, data } = this.state;
return (
<div className="list">
<Table rowKey="ref" loading={loading} dataSource={this.orderBy(data.data)} size="large" />
</div>
);
}
I have a Dashboard component that renders an array of cards with data fetched from a backend server. Users can create additional cards by submitting a form, which then redirects them back to the dashboard page.
My issue is that when the form is submitted, a javascript error 'cannot read property "includes" of undefined' is thrown and the dashboard does not render. If I manually refresh the page, the list renders as expected with the new card. I use Array.includes method to filter the cards based on the filterText state value. Does this error happen because the data has not been fetched when render is called? If so, how can I force the component to wait until there is data before rendering? Please see the components and redux action below.
const CardList = (props) => {
const cards = props.cards.map(({ _id, title}) => {
return (
<Card key={_id} title={title} />
)
});
return (
<div className="container">
<input onChange={ (e) => props.handleChange(e.target.value) } />
<div className="row">
{cards}
</div>
</div>
);
}
export default CardList;
export class Dashboard extends Component {
constructor(props) {
super(props);
this.state = {
filterText: ''
}
}
componentDidMount() {
this.props.fetchCards();
}
handleChange = (filterText) => {
this.setState({filterText});
}
render() {
const cardList = this.props.cards.filter(card =>
card.title.includes(this.state.filterText.trim().toLowerCase())
);
return (
<div>
<CardList cards={cardList}
handleChange={filterText => this.handleChange(filterText)} />
</div>
);
}
};
function mapStateToProps({ cards: { cards }}) {
return {
cards,
}
}
export default connect(mapStateToProps, {fetchCards})(Dashboard);
export class SurveyForm extends Component {
render() {
return (
<div>
<form>
<Field component={CardField} type="text"
label={'title'} name={'title'} key={'title'} />
<Button type="submit" onClick={() => submitCard(formValues, history)}>Next</Button>
</form>
</div>
);
}
}
REDUX ACTION DISPATCHER:
export const submitCard = (values, history) => async dispatch => {
const res = await axios.post('/api/cards', values);
try {
dispatch({ type: SUBMIT_CARD_SUCCESS, payload: res.data });
dispatch({ type: FETCH_USER, payload: res.data })
}
catch(err) {
dispatch({ type: SUBMIT_CARD_ERROR, error: err });
}
history.push('/cards');
}
Similar to what #JasonWarta mentioned, it's worth noting that React does not render anything when false, null, or undefined is returned, so you can usually use && to be more succinct than using the conditional ("ternary") operator:
render() {
return this.props.cards && (
<div>
<CardList
cards={this.props.cards.filter(card => card.title.includes(this.state.filterText.trim().toLowerCase())}
handleChange={filterText => this.handleChange(filterText)}
/>
</div>
);
}
Because && short-circuits, the latter part won't be evaluated so you can avoid TypeErrors, and the component will also render no content (same as when you return null).
I've used ternary operators in this kind of situation. You may need to adjust the check portion of the pattern, depending on what your redux pattern is returning. null value is returned if this.props.cards is falsey.
render() {
return (
{this.props.cards
?
<div>
<CardList
cards={this.props.cards.filter(card => card.title.includes(this.state.filterText.trim().toLowerCase())}
handleChange={filterText => this.handleChange(filterText)}
>
</CardList>
</div>
:
null
}
);
}
As an alternative to other answers you can return something else suitable if there is no data in your render function with an if statement. I prefer moving functions like your filter one outside of render. Maybe one other (better?) approach is doing that filter in your mapStateToProps function.
Also, if I'm not wrong you don't need to pass anything to your handleChange function. Because you are getting filterText back from CardList component then setting your state.
cardList = () => this.props.cards.filter(card =>
card.title.includes(this.state.filterText.trim().toLowerCase()));
render() {
if ( !this.props.cards.length ) {
return <p>No cards</p>
// or return <SpinnerComponent />
}
return (
<div>
<CardList cards={this.cardList()}
handleChange={this.handleChange} />
</div>
);
}
in many of my components I am fetching API data and therefor I need to wait until that data was loaded. Otherwise I am getting errors because some methods are, of course, not available.
My api query looks like this
componentDidMount() {
prismicApi(prismicEndpoint).then((api) =>
api.form('everything')
.ref(api.master())
.query(Prismic.Predicates.at("my.page.uid", this.props.params.uid))
.submit((err, res) => {
if (res.results.length > 0) {
this.setState({doc: res.results[0]});
} else {
this.setState({notFound: true});
}
}))
}
For that I've created this structure that I have been using in all of these documents:
render() {
if (this.state.notFound) {
return (<Error404 />);
} else if (this.state.doc == null || !this.state.doc) {
return (<Loading />);
} else {
return (
<div className="page">
{this.state.doc.getSliceZone('page.body').slices.map(function(slice, i){
return (<SliceZone slice={slice} key={i} />)
})}
</div>
)
}
}
I wanted to move this into a component called Document that looks like this here:
export default class Document extends React.Component {
static defaultProps = {
doc: null,
notFound: false
}
static propTypes = {
doc: React.PropTypes.oneOfType([
React.PropTypes.object,
React.PropTypes.array
]),
notFound: React.PropTypes.bool.isRequired
}
render() {
if (this.props.notFound) {
return (<Error404 />);
} else if (this.props.doc == null || !this.props.doc) {
return (<Loading />);
} else {
return (
<div className="page">
{this.props.children}
</div>
)
}
}
}
and then I tried to use it like this here:
<Document doc={this.state.doc} notFound={this.state.notFound}>
{this.state.doc.getSliceZone('page.body').slices.map(function(slice, i){
return (<SliceZone slice={slice} key={i} />)
})}
</Document>
Though on the second example the error messages are showing up quickly (until the data is loaded) and then disappear. What am I doing wrong? Why is the first example working and the second doesnt?
try this
<Document doc={this.state.doc} notFound={this.state.notFound}>
{ this.state.doc && this.state.doc.getSliceZone('page.body').slices.map(function(slice, i){
return (<SliceZone slice={slice} key={i} />)
})}
</Document>
in your variant, you see an error becuase this.state.doc is null, untill data is loaded, and you see null reference exception, looks like.
In 1st case, it does not calculate, in 2nd case it calculates first and then sent as a parameter "children" to your Document control