ReactJS componentDidUpdate not called even after props change - javascript

I'm working with draft-js for react where I make an api call (IN A FUNCTIONAL PARENT COMPONENT) and get contents to be put up in the editor. I have this code to insert the fetched data into the editor after receiving it in props:
Parent Component:
var draftContent = "";
var isContentFetched = false;
const CommentSection = () => {
let response = await fetch(url, {
method: "get",
headers: headers,
});
let query = await response.json(); // read response body and parse as JSON
draftContent = element.comment;
isContentFetched = true;
return(<RichTextEditor
isDraftFetched={isDraftFetched}
isContentFetched={isContentFetched}
placeholder=""
rows={6}
boxWidth="100%"
boxHeight="155px"
/>)
})
Editor Component:
componentDidUpdate(props) {
if(this.props.isContentFetched == true && draftAlreadyFilled== false) {
this._insertText(this.props.draftContent);
draftAlreadyFilled = true;
}
}
_insertText(htmlContent) {
this.setState({
editorState: EditorState.createWithContent(
ContentState.createFromBlockArray(
convertFromHTML(htmlContent)
)
),
})
}
Problem is, the text loaded and sent through props does not fill up in the editor. Instead once I am in the page and I click on refresh, then it loads fine.
PS: 1. I have checked related questions and those solutions did not work. 2. It is really necessary that I make the API call in the parent component.

Related

Open Modal CSS with Ajax without jQuery

I have a project here, in there:
I have 5 different HTML Web Form, each one already named, example (form1.html, form2.html...)
I did the Modal with CSS (demo image below), currently I open it with a HTML Anchor like "#ModalName" for example.
But, in all pages I need to put all Modal HTML inside all HTML,
I would like a help to Open my CSS Modal with Ajax, Send it with Ajax using JavaScript not jQuery and when form successfully or not comeback to the page with opened modal with the success or denied submit answer.
All example I have saw there are using jQuery and I need some Pure JavaScript.
Tks
DEMO IMAGE
That's difficult to understand, I can give it a shot though. I don't know if this is what you mean but maybe it will help to get the ball rolling.
Lets say you build a modal
function RandomId() {
return Math.random().toString(36).substring(2, 9)
}
function CustomModal() {
function render(config = {}) {
const { modalName = '' } = config
const id = RandomId()
const template = `
<div class="modal ${modalName}" data-id="${id}">
<div class="modal__content"></div>
</div>
`
return { id, template }
}
function open(config = {}) {
const { onRender } = config
const _render = render(config)
const modal_id = _render.id
const template = _render.template
const modal = document.querySelector(`.modal[data-id="${modal_id}"]`)
document.querySelector('#main').insertAdjacentHTML('beforeend', template)
if (onRender) onRender(modal)
// now that you have a specific modal you can add event listeners to this specific one
document.querySelectorAll('.modal').forEach(modal => {
if (modal.dataset.id !== modal_id) {
/*
Here you could remove classes or style attributes
like opacity or transition for example. This would close
the previous modal when a new one is opened
*/
}
})
}
function close() {
document.querySelector('.modal').remove()
}
return { open, close }
}
const customModal = CustomModal()
Now you got a bare bones modal in vanilla js with no jquery. Here is how you could use it in your code:
customModal.open({
modalName: 'modal-1',
onRender(modal) {
const formContent = document.querySelector('#some-form').cloneNode(true)
modal.querySelector('.modal-content').append(formContent)
// here you could add in some dynamic event listeners
// for example a form submit event
const form = document.querySelector('#login-form')
form.addEventListener('submit', e => {
e.preventDefault()
fetch('/login-enpoint', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
firstName: document.querySelector('#first_name').value,
lastName: document.querySelector('#last_name').value,
email: // ect...
}),
})
.then(res => res.json())
.then(data => {
console.log(data)
// close your modal
customModal.close()
})
})
}
})
another thing you could do:
fetch('/some-endpoint')
.then(res => res.json())
.then(data => {
customModal.open({
onRender(modal) {
// maybe do something with the data
}
})
})

Request Body Missing in Spring while updating using PATCH API in react js

Spring shows - Resolved [org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public com.cg.bookstore.entities.OrderDetails com.cg.bookstore.controller.OrderDetailsController.updateDeliveryStatus(int,java.lang.String)]
Console shows - Uncaught (in promise) Error: Request failed with status code 400
class UpdateOrder extends Component {
state = {
deliveryStatus:""
}
handleChange = (event) => {
const deliveryStatus = { ...this.state.deliveryStatus };
this.setState({ deliveryStatus: event.target.value });
};
handleSubmit = (event) => {
// Prevents default behaviour of submit button
event.preventDefault();
console.log(this.state.deliveryStatus)
console.log()
OrderService.updateDeliveryStatus(this.props.match.params.orderDetailsId,this.state.deliveryStatus)
.then((res) => {
this.props.history.push("/admin/orders");
});
};
In OrderService I call the updateDeliveryStatus
async updateDeliveryStatus(orderId,deliveryStatus){
return await axios.patch(BASE_URL+"/"+orderId,deliveryStatus)
}
The updateDeliveryStatus service in spring
#Override
public OrderDetails updateDeliveryStatus(int orderId, String deliveryStatus)
{
Optional<OrderDetails> opt = orderDetailsRepo.findById(orderId);
OrderDetails od;
if (opt.isPresent())
{
od = opt.get();
od.setDeliveryStatus(deliveryStatus);
orderDetailsRepo.save(od);
} else
{
throw new OrderDetailsNotFoundException("Order is not found");
}
return od;
}
While I was testing backend in POSTMAN , I pass the input as plain string and it works fine. Is it because the input in not in form of json the issue? How to fix this ?
Usually, when using #PutMethod and wanting to update a resource you need to provide both ID of the resource you want to update and the new body, which in this case I presume is 'OrderDetails', error suggests is missing there.
Without java controller code it's only assumptions though.

How execute javascript after a component change in angular?

My code works fine when I write in browser localhost:4200/pay;id=1. This show Pay component with credit card fields generated by a external javascript (This javascript script is loaded from this component). But if i come from another component to this, Pay component doesn't show the credit card fields but load external script. How can I fix this?
My code
first.component.ts
let datos = {
id:'6'
}
this.router.navigate(['pay',datos]);
pay.component.ts
ngOnInit(): void {
this.loadScripts();
}
loadScripts() {
this.dynamicScriptLoader.load('2payjs').then(data => {
// Script Loaded Successfully
console.log('All elements loaded successfully')
this.loadElement();
}).catch(error => console.log(error));
}
loadElement(){
let that = this;
let id = this.router.snapshot.paramMap.get('id');
window.addEventListener('load', function() {
// Initialize the JS Payments SDK client.
let jsPaymentClient = new TwoPayClient('AVLRNG');
// Create the component that will hold the card fields.
let component = jsPaymentClient.components.create('card');
component.mount('#card-element');
// Handle form submission.
document.getElementById('payment-form').addEventListener('submit', (event) => {
event.preventDefault();
/// Extract the Name field value
const billingDetails = {
name: document.querySelector('#name').value
};
// Call the generate method using the component as the first parameter
// and the billing details as the second one
jsPaymentClient.tokens.generate(component, billingDetails).then((response) => {
//console.log(response.token);
let data = {
token:response.token
}
}).catch((error) => {
console.error(error);
});
});
});
}
const navigationExtras: NavigationExtras = {
queryParams: {
id: 1,
},
queryParamsHandling: 'merge'
};
this.router.navigate(['pay'], navigationExtras);
you need navigationExtras in order to create params in your router link and able to fetch by another component
Already solved. I just delete window load event listener.

Using API JSON data in react conditional return

I have a small (never for production) Express/React app, I'm validating a hashed pin in express and returning either message: false if validation fails or message: <cardnumber> if validation is succefull. In my react frontend I want to eventually redirect if it returns a cardnumber, but first I'm just trying to conditionally render a component.
I have a constructor for the json response
constructor() {
super();
this.state = {
cardnumber: '',
pin: '',
servercardnumber: {
message: ''
}
};
Then I'm getting the data from API like this
const url = '/api/login';
const serverResponse = await fetch(url, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': true
},
body: JSON.stringify(data)
});
const json = await serverResponse.json();
console.log(json);
this.setState(
prevState => {
return {
servercardnumber: json.cardnumber
};
},
() => {
console.log(this.state.cardnumber);
}
);
};
Then I'm trying to conditionally render a material ui component in my react return
render() {
const { cardnumber, pin, servercardnumber } = this.state;
return (
<React.Fragment>
<Card>{!servercardnumber ? <Card> Server says no</Card> : null}</Card>
{console.log('server says:')}
{console.log(servercardnumber)}
The {console.log(servercardnumber)} first returns the correct servercardnumber, then returns undefined.
What I need is to see the response in my conditional render, and show the rendered component if login is succefull (or show if not succefull, as long as I get it to conditionally render)
I've done a bunch of changes to this code in my attempt to get this to work, so it may seem a bit cluttered.
Full front end code for the relevant file: https://pastebin.com/VbdzmE4E
Server code for the relevant file: https://pastebin.com/TZ35NZxa
Reposting my comment here so that it the question can be resolved.
The state property servercardnumber should be set to json.message instead of json.cardnumber.

Reactjs: Loading view based on response

Looking for a way for React to process some json, and load views based on the response.
For example:
1- React has a form, response goes out to external API
2- API processes the input, returns a success code unless there was validation issues, and send a response back to the React app
3- React gets the json response, loads a "Success" view, or reloads the form and outputs the erros
Is there a simple way for React to handle this? Thanks in advance!
Very simple...
Basically, you need to track when you initiate request (sending data) and when request is completed (receiving response).
Based on data returned, you decide what to render...
Take a look at this example (working fiddle)
// In this example, we are using JSONPlaceholer service do real
// request and receive response;
const root = 'http://jsonplaceholder.typicode.com';
const Success = () => (<div>Success!</div>);
const Error = () => (<div>Error! Fix your data!</div>);
const Form = React.createClass({
getInitialState() {
return {
processing: false,
result: undefined,
};
},
submit(event) {
this.setState({ processing: true });
event.preventDefault();
fetch(`${root}/posts`, {
method: 'POST',
data: {
// your data here...
}
})
.then(response => {
// We simulate succesful/failed response here.
// In real world you would do something like this..
// const result = response.ok ? 'success' : 'error';
const processing = false;
const result = Math.random() > 0.5 ? 'success' : 'error';
this.setState({ result, processing });
});
},
render() {
const { result, processing } = this.state;
if (result === 'success')
return <Success />;
return (
<form>
Form content here<br/>
<button onClick={this.submit}>
{ processing ? 'Sending data...' : 'Submit' }
</button>
{ result === 'error' && <Error /> }
</form>
);
},
});
render(<Form />, document.getElementById('root'));
The easy way would be to trigger the new state with setState() from the API callback function such as in the example below, although I recommend using a library such as Redux for state management.
var MainComp = React.createClass({
getInitialState: function() {
return {someProp: ""}
},
callAPI: function() {
var root = 'http://jsonplaceholder.typicode.com';
$.ajax({
url: root + '/posts/1',
method: 'GET'
}).then(function(data) {
this.setState({someProp: data.body})
}.bind(this));
},
render: function(){
return (
<div>
<h2>{this.state.someProp}</h2>
<button onClick={this.callAPI}>Async</button>
</div>
)
}
});
React.render(<MainComp/>, document.getElementById("app"));
Please note this is a naive example, you should still cover up error cases and build a logic to trigger different views based on state.

Categories

Resources