I am trying to re-render the page based on a button click. I have the function updateCowList which calls setState() in my app component. The handleClick logic is in my newCow component which handles the button and the text input.
The console.logs() that I am seeing are 'fire', but I am not seeing the 'after' console.log(), nor am I seeing any of the logs within my updateCowList function in App.
How can I get my updateCowList function to run? I have tried calling it in all sorts of ways, destructuring props, etc.
Here is my App:
import React from 'react';
import CowList from './CowList.jsx';
import CowListEntry from './CowListEntry.jsx';
import axios from 'axios';
import SearchDB from './searchDB.js';
import NewCow from './NewCow.jsx';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
cows: []
}
// this.updateCowList = this.updateCowList.bind(this);
}
componentDidMount() {
SearchDB()
.then((res) => {
this.setState({cows: res.data})
}, (err) => {
console.log(err);
});
}
updateCowList(cow) {
console.log('update cow list is running')
oldCows = [...this.state.cows];
newCows = oldCows.push(cow);
console.log('new cows be4 set state', newCows);
this.setState({cows: newCows});
console.log('new cows after set state', newCows);
}
render() {
return (
<div>
<CowList cows={this.state.cows}/>
<NewCow props={this.updateCowList}/>
</div>
)
}
}
export default App;
here is my NewCow component:
import React from 'react';
import axios from 'axios';
class NewCow extends React.Component {
constructor(props) {
super(props);
this.state = {
entry: ''
};
this.handleChange = this.handleChange.bind(this);
this.handleClick = this.handleClick.bind(this);
}
handleClick () {
let split = this.state.entry.split(', ')
console.log(split)
axios.post('http://localhost:3000/api/cows', {
name: split[0],
description: split[1]
})
.then(res => { console.log('fire', res.data);
this.props.updateCowList(res.data);
console.log('after')
})
.catch(err => 'error submitting cow :( mooooo');
}
handleChange (event) {
this.setState({entry: event.target.value})
}
render () {
return (
<div className='newCowForm'>
<input className='form-control' type='text' onChange={this.handleChange} value={this.state.entry} placeholder={'name, description'} />
<button onClick={this.handleClick} className='newCowButton'>Create new cow</button>
</div>
)
}
}
export default NewCow;
<NewCow props={this.updateCowList}/>
should be :
<NewCow updateCowList={this.updateCowList}/>
Related
I am having an issue where I'm trying to pass a function(updateEvents) via props from my App.js file to a NumberOfEvents.js file. I passed the same function to another component with no issues. However, when I try on the NumberOfEvents file, I get the following error:
Error image
Please help!!!
Here is the Parent:
import React, { Component } from 'react';
import EventList from './EventList';
import CitySearch from './CitySearch';
import NumberOfEvents from './NumberOfEvents';
import { extractLocations, getEvents } from './api';
import './nprogress.css';
import './App.css';
class App extends Component {
state = {
events: [],
locations: [],
numberOfEvents: 32
}
componentDidMount() {
this.mounted = true;
getEvents().then((events) => {
if (this.mounted) {
this.setState({
events: events.slice(0, this.state.numberOfEvents),
locations: extractLocations(events)
});
}
});
}
componentWillUnmount() {
this.mounted = false;
}
updateEvents = (location, eventCount) => {
this.mounted = true;
getEvents().then((events) => {
const locationEvents = (location === 'all')
? events
: events.filter((event) => event.location === location);
this.setState({
events: locationEvents,
numberOfEvents: eventCount,
});
});
};
render() {
return (
<div className="App">
<CitySearch
locations={this.state.locations} updateEvents={this.updateEvents} />
<EventList
events={this.state.events} />
<NumberOfEvents
numberOfEvents={this.state.numberOfEvents}
updateEvents={this.updateEvents} />
</div>
);
}
}
export default App;
And here is the Child:
import React, { Component } from 'react';
class NumberOfEvents extends Component {
state = {
numberOfEvents: 32
}
handleChange = (event) => {
const value = event.target.value;
this.setState({
numberOfEvents: value,
});
this.props.updateEvents('', value);
};
render() {
return (
<input
className="number"
value={this.state.numberOfEvents}
onChange={this.handleChange} />
)
}
}
export default NumberOfEvents;
Im not sure this will help ...In Your Parent Component , inside return statement when passing the updateEvents Prop, try passing it as arrow function like this ....
updateEvents={ () => this.updateEvents() } />
try adding a constructor to the child component
constructor(props) {
super(props);
this.state = {
numberOfEvents: 32
}
}
I have an issue in figuring in what conditions props are not passed down by the tree. I have a Fetcher class in which I populate with "layouts", then pass it to children props, but I cannot access it from child component.
EX:
import React, { Component } from 'react'
import axios from "axios";
export default class Fetcher extends Component {
constructor(props) {
super(props)
this.state = {
layouts: [],
}
componentDidMount() {
this.getLayouts();
}
getLayouts = () => {
axios
.get("/layout")
.then((res) => {
this.setState({
layouts: res.data,
});
})
.catch((err) => console.log(err));
};
render() {
return (
this.props.children(this.state.layouts)
)
}
}
This is my Parent component on which I pass some props children:
ex:
import React, { Fragment } from "react";
import Fetcher from "./Fetcher";
class App extends Component {
<Fetcher>
{(layouts) => {
return <Fragment>
<NewLayout
layoutsList={layouts} />
</Fragment>
}}
</Fetcher>
}
import React from "react";
class NewLayout extends React.Component {
constructor(props) {
super(props)
this.state = {
layouts: [],
}}
componentDidMount() {
this.setState(() => ({
layouts: this.props.layoutList
}))
}
render() {
{ console.log(this.state.layouts) }
{ console.log(this.props.layoutList) }
return (
....
The children prop is not a function, if you want to pass a property to it you should use React.Children API with React.cloneElement:
class Fetcher extends Component {
state = {
layouts: [/*some layout values*/],
};
render() {
const children = this.props.children;
const layouts = this.state.layouts;
return React.Children.map(children, (child) =>
React.cloneElement(child, { layouts })
);
}
}
Typo my friend, looks like you pass layoutsList prop to NewLayout, but internally use layoutList.
I have a component that contains a state, and I will pass the state data into another component, I use a static contextType to throw the state data but the data does not reach the intended component, what do you think this is wrong? thank you
this is my parent component
export const MyContext = React.createContext();
export class MerchantByPromo extends Component {
constructor(props) {
super(props);
this.state = {
dataPromo: [],
loading: true
};
}
async componentDidMount() {
const merchant_id = this.props.match.params.id_merchant
await Api.post('language/promo-voucher-by-merchant', { MERCHANT_ID: merchant_id })
.then((response) => {
if (response.data.STATUS_CODE === '200') {
this.setState({
dataPromo: response.data.DATA,
loading: false
});
}
})
}
this is my child component
import React, { Component } from 'react'
import { MyContext } from './MerchantByPromo'
export class MerchantByPromoDetail extends Component {
constructor(props){
super(props)
this.state = {
detailPromo:[],
}
}
UNSAFE_componentWillMount(){
let value = this.context
console.log(value)
}
componentDidMount(){
}
render() {
return (
<MyContext.Consumer>
<p>tes</p>
</MyContext.Consumer>
)
}
}
I always get an error message like this "TypeError: render is not a function", what's the solution?
<MyContext.Consumer>
{() => <p>tes</p>}
</MyContext.Consumer>
change to this and Check
I am serving some content from my API.
I want display response from API in my react component.
Response is html with bundled all assets inline by webpack.
How can I do it?
I tried dangerouslySetInnerHTML but it crashes my javascript inside returned html.
My cmp :
import React, { Component } from 'react';
import axios from 'axios';
export default class Report extends Component {
constructor() {
super();
this.state = {
id: null,
report: null
};
}
getParam(param){
return new URLSearchParams(window.location.search).get(param);
}
componentWillMount() {
axios.post(`/url`,
{
'id': this.getParam('id'),
}
)
.then(res => {
this.setState({id: res.data});
setTimeout(() => {
axios.get(`https://rg.ovh/`+this.state.id)
.then(res => {
this.setState({report: res.data})
});
}, 1900);
});
}
render() {
return (
<div dangerouslySetInnerHTML={ {__html: this.state.report} } />
);
}
}
import axios from 'axios';
import React, { Component } from 'react';
import renderHTML from 'react-render-html';
class App extends Component {
constructor() {
super();
this.state = {
htmlString: ''
};
}
componentDidMount() {
axios.get('http://localhost:5000').then(response => {
this.setState({ htmlString: response.data })
}).catch(err => {
console.warn(err);
});
}
render() {
const { htmlString } = this.state;
return (
<div className="App">
{renderHTML(htmlString)}
</div>
);
}
}
export default App;
hi I am trying to post a form with email and password, but I have an error in the function that sends the data, that function you see in the image
action.js
import axios from 'axios';
export const createUser =(usuariosBody, callback) => {
return function(dispatch){
dispatch({type: 'CREATE_USER_REQUEST'});
axios.post('http://localhost:8080/users', usuariosBody)
.then((response)=>{
dispatch({type: 'CREATE_USER_SUCCESS', payload:response.data})
if (typeof callback === 'function') {
callback(null, response.data);
}
})
}
}
component.jsx
class LoginComponent extends Component{
constructor(props) {
super(props);
}
componentDidMount() {
}
render(){
return(
<section className="form-sign brown lighten-5">
<form onSubmit={this.handleSubmit.bind(this)}>
<input ref="email" placeholder='Email' />
<input type="password" ref="password" />
<Button type='submit' >send</Button>
</form>
</section>
)
}
handleSubmit(event) {
this.preventDefault();
const email = ReactDOM.findDOMNode(this.refs.email).value.trim();
const password = ReactDOM.findDOMNode(this.refs.password).value.trim();
// create a user object
const user = {
email,
password
};
// call the action
this.props.createUser(user, function (err, res) {
if (err) {
console.error(err);
} else {
console.log(res);
}
});
}
}
export default LoginComponent;
container.jsx
import React, {Component} from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import {createUser} from '../action/action.js';
import {LoginComponent} from '../component/loginComponent.jsx';
class CreateUserContainer extends Component{
componentDidMount(){
}
render (){
return (<LoginComponent createUser={this.props.createUser} />);
}
}
function mapStateToProps(store) {
return {};
}
function mapDispatchToProps(dispatch){
return bindActionCreators({
createUser:CreateUser
}, dispatch)
}
export default connect(mapStateToProps, mapDispatchToProps)(CreateUserContainer);
thanks for your help
You are importing {CreateUser} and trying to use {createUser} in the container.jsx file.
You need to use mapDispatchToProps instead of matchDispatchToProps and also
use CreateUser in you mapDispatchToProps function since you imported it as CreateUser
class CreateUserContainer extends Component{
constructor(props) {
super(props);
}
componentDidMount(){
}
render (){
return(
<LoginComponent createUser={this.props.createUser} />
)
}
}
function mapDispatchToProps(dispatch){
return bindActionCreators({
createUser:CreateUser
}, dispatch)
}
Also your class must implement the constructor to inherit the props
One more thing is that your handleSubmit function in LoginComponent is not bound
class LoginComponent extends Component{
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
}
You can also try and console.log(this.props) in your LoginComponent to see if it receives the createUser function