I have this class component where I'd like to fetch the response from server to an state array so I can pass further the elements to another component as props, so far I have this:
export default class MainApp extends Component {
state = {
posts: [],
}
constructor(props){
super(props);
const request = new FetchRequest();
request.setAmount(this.props.amount);
request.setUserid(this.props.token);
request.setSeenpostsList(this.props.seenPosts);
var stream = client.fetchPosts(request, {});
stream.on('data', function(response) {
this.setState({
posts: [...this.state.posts, response.array]
})
});
}
render(){
return(
<div className="main-app">
<Navbar />
<Postbox token = {this.props.token}/>
{this.state.posts.map(element =>
<Postcard username = {element[0]}/>
)}
</div>
)
}
With this code I get TypeError: Cannot read properties of undefined (reading 'posts').
What is the correct way to do it?
Your state needs to be initialised within the constructor() {}
constructor(props) {
super(props);
this.state = {
posts: []
}
}
Here's info you might also want to read
Related
In my react application, I have a child component LoginForm as follows:
export class LoginForm extends React.Component {
constructor(props) {
super(props);
this.login = this.login.bind(this);
}
async login() {
let data = new FormData();
data.append('User[email]', document.getElementById('app-login-form-email').value);
data.append('User[password]', document.getElementById('app-login-form-password').value);
let loginHandler = this.props.loginHandler;
const req = await fetch('/site/login', {
method: 'POST',
body: data
});
const respJson = await req.json();
loginHandler(respJson);
}
render() {
return(
<div id="app-login-form">
<input type="text" id="app-login-form-email" value="test#app.com"></input>
<br/>
<input type="password" id="app-login-form-password" value="admin"></input>
<br/>
<button onClick={this.login}>Login</button>
</div>
);
}
}
It has a prop loginHandler, which is a function passed down from the parent component, seen here in full:
export class App extends React.Component {
constructor(props) {
super(props);
this.state = {
user: {
isAuthenticated: props.isAuthenticated || false
}
}
this.bodyHandlers = {
handleUserLogin: this.handleUserLogin,
};
this.handleUserLogin = this.handleUserLogin.bind(this);
}
bodyHandlers;
headerHandlers;
footerHandlers;
handleUserLogin(responseJson) {
this.setState({
user: {
isAuthenticated: true,
data: responseJson.user,
jwt: responseJson.token
}
});
}
render() {
return(
<Router>
<Header user={this.state.user} handlers={this.headerHandlers}/>
<Body user={this.state.user} handlers={this.bodyHandlers}/>
<Footer user={this.state.user} handlers={this.footerHandlers}/>
</Router>
);
}
}
const domContainer = document.querySelector('#main');
ReactDOM.render(React.createElement(App), domContainer);
However whenever I try this, I get the following error in the console:
Uncaught (in promise) TypeError: Cannot read property 'setState' of undefined
I have a basic understanding that when working within the bounds of a promise, this becomes tricky to deal with. I have tried many different permutations, including setting a variable local to the function that to this. I have also tried the fetch .then syntax too, which makes no difference.
Am I going to have to implement the fetch code as a function in the parent component and pass it down as a prop for the child component to call, or am I missing something?
Thanks.
I think the problem is that you are assigning the method as a value to bodyHandlers object before binding it. Try switching the order:
constructor(props) {
super(props);
this.state = {
user: {
isAuthenticated: props.isAuthenticated || false
}
}
this.handleUserLogin = this.handleUserLogin.bind(this);
this.bodyHandlers = {
handleUserLogin: this.handleUserLogin,
};
}
I'm working in react.js. I've created a component Backend.jsx. I want it to work as a service (like in angular) where I can send API requests. I want to call methods of Backend in some other components.
I called this backend service in component and try to send data and get it in BackendService using props.
But obviously this will not work.
Here's my code
In Component:
This will be called after form submit.
handleLoginSubmit = (event) => {
event.preventDefault();
console.log(this.state.data);
<BackendService onSendData = {this.state.data} />
}
In BackendService:
constructor(props) {
super(props);
this.state = { }
this.login(props)
}
login = (props) =>
{
console.log('login', props);
};
Any suggestions how can I call this login method in component. Or any other suggestion to get component data in service.
You can try this:
1.Component.js
class Componet extends React.Component {
constructor(props) {
super(props);
this.state={
data:"this state contain data"
}
this.backendServiceRef = React.createRef(); // Using this ref you can access method and state of backendService component.
}
render() {
return (
<div className="App">
<button onClick={() => {
this.backendServiceRef.current.login()
}}>click</button>
<BackendService ref={this.backendServiceRef} onSendData = {this.state.data}></BackendService>
</div>
);
}
}
export default Componet;
2.BackendService.js
class BackendService extends React.Component {
constructor(props) {
super(props);
this.state = {
}
}
login = (props) => {
alert("login call")
};
render() {
return (
<div>
Backend service component
</div>
)
}
}
After I execute a query in the console I can see: {data:{action: [...]}. How can I assign that data to a variable in a React component?
Trying this but it is not working:
class MyGraph extends React.Component {
constructor(props) {
super(props);
this.state = {
nodes: this.data
Have some falsy or empty initial value for state.node. Then fetch the data in componentDidMount - on success, update state.node with your actual data. That data can also be passed down to child components. Example:
class MyGraph extends React.Component {
constructor(props) {
super(props);
this.state = {
nodes: null,
}
}
componentDidMount() {
// w/e your fetch function is. I'm assuming your method uses promises.
fetchDataSomehow().then((response) => {
this.setState({nodes: response.data}) // or whatever property has the nodes
})
}
render() {
const nodes = this.state.nodes;
return (
<LoadingIcon isVisible={!nodes}>
{(nodes || []).map((node) => (
<MyCircle key={node.someUniqueId} node={node} /> // access `node` inside the `<MyCircle />` component using `this.props.node`
))}
</LoadingIcon>
)
}
}
You'll need to handle what happens/renders while the data is still loading (e.g the made-up <LoadingIcon /> component).
Since upgrading to using Gatsby V2 I have been struggling to pass this.state to child components to be used as this.props.
For Example I have a Container that has data1 and data2 added to this.state as
class Parent extends React.Component {
constructor(props) {
super(props);
this.state = {
data1: '',
data2: ''
};
}
componentDidMount() {
// Loading database
.then(doc =>
this.setState({
data1: doc.data().data1,
data2: doc.data().data2
})
);
}
render() {
const children = this.props;
const stateAsProps = React.Children.map(children, child =>
React.cloneElement(child, {
data1: this.state.data1,
data2: this.state.data2
})
);
return (
<div>{stateAsProps}</div>
);
}
}
and a child component as
class Child extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<h1>{this.props.data1}</h1>
<p>{this.props.data2}</p>
);
}
}
and finally this is brought into the page by
const Page = () => (
<Parent authUserID="01234" campaignID="56789">
<Child />
</Parent>
);
In Gatsby V1 this was working but now with the migration I am receiving an error Uncaught Error: Objects are not valid as a React child (found: object with keys {authUserID, campaignID, children}). If you meant to render a collection of children, use an array instead.
Can anyone advise to why and how this issue can be rectified?
You are using the entire props object as children in your Parent component. Make sure you destructure out the children object from the props instead and it will work as expected.
const { children } = this.props;
I am trying to play around with the wikipedia API. I'm using Axios to make a request for the data. When I go to map through the prop passed through from App's state, I get the following error:
Uncaught TypeError: search.map is not a function
I have checked that the intended value is an array. It seems to be, I can manipulate it as such in the react dev tools console. It also has a proto of Array, so I'm confused as to why I can't do this.
Root Component:
class App extends React.Component
{
constructor()
{
super();
this.state = {search: {}}
this.wikiSearch();
}
wikiSearch()
{
axios
.get('https://en.wikipedia.org/w/api.php?action=opensearch&search="test"')
.then ((result) => {
result.data.shift();
this.setState({search: result.data});
});
}
render ()
{
return(
<div id="container">
<Header />
<SearchBar />
<SearchList search={this.state.search} />
</div>
);
}
}
export default App;
The component that uses state data from App
class SearchList extends React.Component
{
render()
{
let search = this.props.search;
search.map((element) => {
});
return(
<div id='SearchList'>
</div>
);
}
}
You need to initialize search as an empty array variable, not object, in your component state so that it's not throw erro on calling map method on it like this:
this.state = {search: []}
not like this:
this.state = {search: {}}