renderToString with Redux store renders populated without props (server side) - react-redux

Although the story id properly prefilled, renderToString() still renders the app without the state being filled in via mapStateToProps().
I use selectors to get data from state.
The problem is, that the props are not being populated. On the client, everything works.
Anyone ideas?
THANKS!
Here's the code for the server side operation:
app.use('*', (req, res) => {
// // Create a new Redux store instance
const sagaMiddleware = createSagaMiddleware();
let middleware = applyMiddleware(sagaMiddleware);
// middleware = compose(middleware,thunkMiddleware)
const initialState = {};
const store = createStore(reducers,initialState,middleware);
store.runSaga = sagaMiddleware.run;
store.close = () => store.dispatch(END);
const routes = getRoutes(store.getState)
const tres = res;
const url = req.originalUrl;
const urlSplit = url.split('/');
match({ routes: routes, location: req.url }, (err, redirect, props) => {
if (err) {
tres.status(500).send(err.message)
} else if (redirect) {
tres.redirect(redirect.pathname + redirect.search)
} else if (props) {
if(urlSplit[1]==='story'){
let slug = urlSplit[2];
store.runSaga(waitAll([[getStoryBySlug,host,slug], [getAbout, host]])).done.then(() => {
res.end(renderPage(store,props,tres));
});
}else{
store.runSaga(waitAll([[getAbout, host], [getHome, host]])).done.then(() => {
res.end(renderPage(store,props,tres));
});
}
} else {
tres.status(404).send('Not Found')
}
})
});
And here are the actual renderPage and renderFullPage functions:
const renderPage = (store,props,res) => {
// Render the component to a string
const html = renderToString(
<Provider store={store}>
<RouterContext {...props}/>
</Provider>
)
let head = Helmet.rewind();
const preloadedState = fromJS(store.getState());
return renderFullPage(html, preloadedState, head);
}
const renderFullPage = (html, preloadedState, head) => {
return `
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
${head.title.toString()}
${head.meta.toString()}
${head.link.toString()}
<script src="https://use.typekit.net/yzi3zgu.js"></script>
<script>try{Typekit.load({ async: true });}catch(e){}</script>
<link href="/assets/fonts/GillSans/stylesheet.css" rel="stylesheet"/>
<link href="/assets/vendors/fullpage/jquery.fullPage.css" />
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous" />
<link rel="shortcut icon" href="/assets/icons/favicon-inv.png" />
<link rel="stylesheet" href="/styles.css" />
</head>
<body>
<div id="root">${html}</div>
<script>
window.__PRELOADED_STATE__ = ${JSON.stringify(preloadedState)}
</script>
<script src="/vendor.js"></script>
<script src="/main.js"></script>
</body>
</html>
};

Related

Reply not working in laravel using botman

I want to create an automatic chat system with Botman, but I have a problem. I do not receive a response when I send a message, and i get this message in console, "chat.js:1 POST http://127.0.0.1:8000/botman 404 (Not Found) (anonymous) # chat.js:1 t.exports # chat.js:1 t.exports # chat.js:1 Promise.then (async) r.request # chat.js:1 r. # chat.js:1 (anonymous) # chat.js:1 callAPI # chat.js:1 e.say # chat.js:1 r.handleKeyPress # chat.js:1 m # chat.js:1 chat.js:1 Uncaught (in promise) Error: Request failed with status code 404 at t.exports (chat.js:1:13996) at t.exports (chat.js:1:17470) at d. (chat.js:1:12823)" So here is my code
//route :
Route::get('/show_my_chat_form', 'BotManController#index')->name('chatform');
Route::get('/botman', 'BotManController#handle');
Route::post('/botman', 'BotManController#handle');
//here is my Controller
use BotMan\BotMan\BotMan;
use Illuminate\Http\Request;
use BotMan\BotMan\Messages\Incoming\Answer;
class BotManController extends Controller
{
public function index()
{
return view('chatform');
}
public function handle($language)
{
$botman=app("botman");
$botman->hears("{message}", function($botman,$message)
{
if ($message == "Hello")
{
$this->askName($botman);
}
else
{
$botman->reply("Please write hi to start conversation! ");
}
});
$botman->listen();
}
public function askName($language,$botman)
{
$botman->ask("what's your name? ", function(Answer $answer)
{
$name=$answer->getText();
$this->says("nice to met you M.-Mm ".$name);
});
//the config.php and web.php located in /config/botman/..
//config.php
<?php
return [
'conversation_cache_time' => 40,
'user_cache_time' => 30,
];
//web.php
<?php
return [
'matchingData' => [
'driver' => 'web',
],
];
//view
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Form</title>
<link href="https://fonts.googleapis.com/css?family=Nunito:200,600" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/botman-web-widget#0/build/assets/css/chat.min.css">
<style>
html,
body {
background-color: #fff;
color: #636b6f;
font-family: 'Nunito', sans-serif;
font-weight: 200;
height: 100vh;
margin: 0;
}
</style>
</head>
<body>
</body>
<script>
var botmanWidget = {
aboutText: 'write',
introMessage: "✋hi",
//frameEndpoint: ''
};
</script>
<script src='https://cdn.jsdelivr.net/npm/botman-web-widget#0/build/js/widget.js'></script>
</html>

d3.js v5 stratify returning missing: 0

I have created a very simple test case to use the D3.JS v5 stratify method. Everything looks to be in order based on similar code but mine fails and I am not sure why. Can anyone help?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://d3js.org/d3.v5.min.js"></script>
</head>
<body>
<script>
let csvdata =
`pk,firstname,lastname,email,title,city,statecode,zip,phone,latitude,longitude,fk_staff
1,Thomas,Bellmer,thomas.bellmer#gmail.com,President,Overland Park,KS,66221,9132216533,38.86182,-94.71264,
2,Xnx,Zgulx,xnx.zgulx#gmail.com,Vice President,Royal Palm Beach,FL,33421,5615120044,26.6802,-80.204984,1
3,Kjc,Duxuk,kjc.duxuk#gmail.com,Vice President,Newtown,IN,47969,7656204292,40.205844,-87.148287,1`
;
data = d3.csvParse(csvdata);
data.forEach(function(d) {
d.pk = +d.pk;
d.fk_staff = +d.fk_staff;
});
console.log(data);
let root = d3.stratify()
.id(function(d) { return d.pk; })
.parentId(function(d) { return d.fk_staff; })
(data);
console.log(root);
</script>
</body>
</html>
The issue is happening here:
data.forEach(function(d) {
d.pk = +d.pk;
d.fk_staff = +d.fk_staff;
});
Some of the data has an empty string as d.fk_staff. When the empty string is coerced to a number it becomes 0, and there is no data with d.pk equals to 0, hence the error.
A simple fix is to not coerce the empty string:
data.forEach(function(d) {
d.pk = +d.pk;
d.fk_staff = d.fk_staff === '' ? '' : +d.fk_staff;
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://d3js.org/d3.v5.min.js"></script>
</head>
<body>
<script>
let csvdata =
`pk,firstname,lastname,email,title,city,statecode,zip,phone,latitude,longitude,fk_staff
1,Thomas,Bellmer,thomas.bellmer#gmail.com,President,Overland Park,KS,66221,9132216533,38.86182,-94.71264,
2,Xnx,Zgulx,xnx.zgulx#gmail.com,Vice President,Royal Palm Beach,FL,33421,5615120044,26.6802,-80.204984,1
3,Kjc,Duxuk,kjc.duxuk#gmail.com,Vice President,Newtown,IN,47969,7656204292,40.205844,-87.148287,1`
;
data = d3.csvParse(csvdata);
data.forEach(function(d) {
d.pk = +d.pk;
d.fk_staff = d.fk_staff === '' ? '' : +d.fk_staff;
});
console.log(data);
let root = d3.stratify()
.id(function(d) { return d.pk; })
.parentId(function(d) { return d.fk_staff; })
(data);
console.log(root);
</script>
</body>
</html>

ERR_NAME_NOT_RESOLVED in OpenWeather Api Call

I'm putting together my first Api project and I'm using OpenWeather to request conditions for a city. When I run my code, I get "ERR_NAME_NOT_RESOLVED." I've checked and rechecked my URL formatting and I'm not getting any errors when running my code. Could anyone point me in the right direction?
My HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script defer src="./js/script.js"></script>
<title>Weatherd</title>
</head>
<body>
<h1>Weatherd</h1>
<form>
<input type="text" placeholder="Search by city"/>
<input type="submit" value="Search"/>
</form>
<main>
<p>Weather for</p>
<p id="weatherFor"></p>
<p>Temperature: </p>
<p id ="temp"></p>
<p>Currently feels like: </p>
<p id="feelsLike"></p>
<p>Conditions: </p>
<p id="desc"></p>
</main>
</body>
</html>
My JS
const $weatherFor = $('#weatherFor');
const $temp = $('#temp');
const $feelsLike = $('#feelsLike');
const $desc = $('#desc');
const $input = $('input[type="text"]');
let weatherData, userInput;
$('form').on('submit', handleGetData);
function handleGetData(event) {
event.preventDefault();
userInput = $input.val();
$.ajax({
url: 'https://www.api.openweathermap.org/data/2.5/weather?q='+userInput+'&APPID=15ff99dd07f18bda25869ab24d06891e'
}).then(
(data) => {
weatherData = data;
render();
},
(error) => {
console.log('bad request', error);
}
);
}
function render() {
$weatherFor.text(weatherData.weatherFor);
$temp.text(weatherData.temp);
$feelsLike.text(weatherData.feelsLike);
$desc.text(weatherData.desc);
}
It's been a while since the question was asked, but given the amount of visits this question has had so far, this answer might help someone.
const url = "api_url_here";
const result = await axios
.get(url)
.then((res) => {
const { status } = res;
return status && status == 200
? { ...res.data, status: 200 } // return data + status 200
: { status: 400 }; // create and return status 400 on error
})
.catch((err) => {
return { status: 400 }; // create and return status 400 on error
});
// work with the returned status
if(result.status == 200) {
// success
} else {
// error
}
I used axios, but the idea is very much transferable to Fetch Api or Ajax.

Load Vue Componet via AJAX

I'd like to load Vue Component via AJAX dynamically and render its template.
Main Vue Instance:
const router = new VueRouter({
path: '/vue/actions/',
mode: 'history'
});
var app = new Vue({
el: '#mainContainer',
router,
data: {
mainContent: ''
},
methods: {
action: function (url) {
alert(url);
this.$router.push({ path: '/vue/actions/?'+url});
console.log(this.$route.query);
},
actions: function () {
var action;
if (!this.$route.query.action || this.$route.query.action == 'main') {
action = 'index';
} else {
action = this.$route.query.action;
}
var mainContent;
fetch('/vue/actions/?content_type=json&action='+action).then((response) => {
if(response.ok) {
return response.json();
}
throw new Error('Network response was not ok');
}).then((json) => {
this.$router.push({ path: '/vue/actions/', query: { action: json.action }});
// this.mainContent = json.template;
console.log(json.template);
this.dynamicComponent = json.template;
}).catch((error) => {
console.log(error);
});
}
},
created: function () {
this.actions();
}
})
Initial Page:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title></title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="" />
<meta name="author" content="" />
<meta http-equiv='cache-control' content='no-cache'>
<meta http-equiv='expires' content='0'>
<meta http-equiv='pragma' content='no-cache'>
<script type="text/javascript" src="/js/vue.min.js"></script>
<script src="/js/vue-router.js"></script>
</head>
<body>
<template><div><component :is="dynamicComponent"></component></div></template>
<div id="mainContainer" v-html="mainContent"></div>
<script type="text/javascript" src="/js/main.js"></script>
</body>
</html>
Component I'd like to load via AJAX:
Vue.component('dynamicComponent', {
template: '<div>Dynamic Component!</div>'
});
Is it possible to load such Vue Componet and render its template (with an ability to use Vue data bindings in the Component template)?
Here is how I got what I need:
Main Vue Instance:
const router = new VueRouter({
path: '/vue/actions/',
mode: 'history'
});
var app = new Vue({
el: '#mainContainer',
router,
data: {
mainContent: ''
},
methods: {
action: function (url) {
this.$router.push({ path: '/vue/actions/?'+url});
console.log(this.$route.query);
},
actions: function () {
var action;
if (!this.$route.query.action || this.$route.query.action == 'main') {
action = 'index';
} else {
action = this.$route.query.action;
}
Vue.component('dynamic-component', (resolve) => {
import('/vue/actions/?content_type=javascript&action='+action).then((component) => {
resolve(component.default);
});
});
}
},
created: function () {
this.actions();
}
})
Main/Initial Page Body:
<body>
<div id="mainContainer">
<dynamic-component></dynamic-component>
</div>
<script type="text/javascript" src="{{.__web_root_folder}}/js/main.js"></script>
</body>
Component code that I'm loading when needed:
export default {
template: '<div>Async Component! {{.test}}</div>',
data () {
return {
test: 'Works!'
}
}
}
Thanks to #MazinoSUkah !

Django Ajax simple Get function

First of all, sorry for stupid question but I'm no coder, so please forgive me :)
I've written simple code in Python which is reading data send through serial port.
It's working really great.
EDIT:
With your help vadimchin I have managed to do something like this.
views.py
class ViewVolt(TemplateView):
template_name = 'view_volt.html'
def __init__(self, voltage=''):
self.voltage = voltage
rs232 = serial.Serial(
port = 'COM15',
baudrate = 38400,
parity = serial.PARITY_NONE,
stopbits = serial.STOPBITS_ONE,
bytesize = serial.EIGHTBITS,
timeout = 1)
line = rs232.readline().decode('utf-8')
if ( 'Pomiar 1' in line ):
index_current = line.find('Prąd')
index_voltage = line.find('Napięcie')
current = line[index_current+6:index_current+11]
self.voltage = line[index_voltage+9:index_voltage+14]
def get_context_data(self, **kwargs):
context = super(ViewVolt, self).get_context_data(**kwargs)
context['ajax_var'] = self.voltage
context['is_ajax'] = self.request.is_ajax()
return context
What I'm trying to do for now is to display only voltage value on my webpage.
urls.py
url(r'^volt/$', ViewVolt.as_view(), name='view_volt'),
view_volt.html
{% if is_ajax %}
<h1>from ajax: {{ ajax_var }}</h1>
{% else %}
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script language="javascript" type="text/javascript" src="{{ STATIC_URL }}admin/js/jquery.min.js"></script>
<script type="text/javascript">
$(function () {
var ping_tm = null;
function _ping() {
$.get('', function (result) {
clearTimeout(ping_tm);
$("div").empty();
$("div").append(result);
ping_tm = setTimeout(_ping, 1000);
})
}
_ping();
});
</script>
</head>
<body>
<div></div>
my doc
</body>
</html>
{% endif %}
As you can see I have modified little bit your view_volt.html template and your View_volt class but it's still does not work as it should be.
Here's a screenshoot.
![Result1]
I have no idea why it's not getting the value's from my serial port all the time.
Thanks in advance...
views.py
logger = logging.getLogger('volt')
class ViewVolt(TemplateView):
template_name = 'frontend/view_volt.html'
def get_context_data(self, **kwargs):
context = super(ViewVolt, self).get_context_data(**kwargs)
logger.debug('my info')
context['ajax_var'] = '1234'
context['is_ajax'] = self.request.is_ajax()
return context
view_volt.html
{% if is_ajax %}
<h1>from ajax: {{ ajax_var }}</h1>
{% else %}
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript" src="/static/js/jquery-2.1.0.min.js"></script>
<script type="text/javascript">
$(function () {
var ping_tm = null;
function _ping() {
$.get('', function (result) {
clearTimeout(ping_tm);
console.log(result);
ping_tm = setTimeout(_ping, 1000);
})
}
_ping();
});
</script>
</head>
<body>
my doc
</body>
</html>
{% endif %}
urls.py
urlpatterns = patterns('',
url(r'^volt/$', ViewVolt.as_view(), name='view_volt'),
)
Ore you can use websocket + gevent
in settings.py add
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'filters': {
'require_debug_false': {
'()': 'django.utils.log.RequireDebugFalse'
}
},
'handlers': {
'mail_admins': {
'level': 'ERROR',
'filters': ['require_debug_false'],
'class': 'django.utils.log.AdminEmailHandler'
},
'file': {
'class': 'logging.handlers.RotatingFileHandler',
'level': 'DEBUG',
'filename': 'log.log'
}
},
'loggers': {
'django.request': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': True,
},
'volt': {
'handlers': ['file'],
'level': 'DEBUG'
}
}
}

Resources