I am learning how to use Redux. I would like to create a simple application with only one button. When the button is clicked I want to do a rest api call and when the response comes back the response content needs to be displayed.
What I would like to do is send a store.dispatch(CardAction.GET_CARDS) message to Redux when user clicks on the button. I do not want to call rest api directly from the button's onClick handler.
When the answer is received I intend to to the same: send an event with store.dispatch(CardAction.UPDATE_UI) and somehow at the background I want to update the Redux's status.
I hope that this concept is align with React + Redux.
I have some JavaScript code done but some part of it are missing. Could you please help me to put parts together?
index.jsp
<!DOCTYPE html>
<%#page session="false"%>
<%#page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<html>
<head>
<meta http-equiv="CONTENT-TYPE" content="text/html; charset=UTF-8">
<base href="${pageContext.request.contextPath}/" />
<link rel="icon" type="image/x-icon" href="public/image/favicon.ico">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/latest/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/latest/css/bootstrap-theme.min.css">
</head>
<body>
<div id="root"></div>
<script type="text/javascript" src="bundle.js"></script>
</body>
</html>
App.js
let store = createStore(reducers);
ReactDom.render(
<Provider store={store}>
<Card/>
</Provider>,
document.getElementById('root')
);
Card.js
export default class Card extends React.Component {
render() {
return (
<div>
...
<Button onClick={() => store.dispatch(CardAction.GET_CARDS)}>rest call</Button>
</div>
)
}
}
ActionType.js
export const GET_CARDS = 'get-cards';
export const UPDATE_UI = 'update-ui';
CardAction.js
export function getCards(param1, param2) {
return createAction(ActionType.GET_CARDS, (param1, param2) => ({ value1, value2 }))
}
export function updateUi() {
return createAction(ActionType.UPDATE_UI)
}
RootReducer.js
export const reducers = (state = {}, action) => {
return action
};
RestClient.js
export default {
cardPost(param1, param2) {
const url = ...;
fetch(url, {
method: 'POST',
credentials: 'include'
})
.then(response => {
if (response.ok) {
console.info('rest response have arrived');
store.dispatch(CardAction.UPDATE_UI)
} else {
console.info('error appeared during calling rest api');
//store.dispatch(CardAction.SHOW_ERROR)
}
})
.catch(function(err) {
console.info(err + ' Url: ' + url)
})
}
}
You should never call store.dispatch() from a component. Instead, you should import a previously built action and let the Redux flow do the remaining stuff. The reducer shouldn't return an action, instead, it should return a new state, without mutating the previous one. I'd suggest you should first compensate some of the comprehensible lack of experience with Redux, and then you can try to follow along with a React-Redux-Rest tutorial like this one: https://medium.com/#rajaraodv/a-guide-for-building-a-react-redux-crud-app-7fe0b8943d0f#.cnat3gbcx
[EDIT]
Here's what I'd do
// component Card.js
import {getCards} from "CardAction";
export default class Card extends React.Component {
render() {
return (
<div>
...
<Button onClick={getCards(param1, param2)}>rest call</Button>
</div>
)
}
}
// action CardAction.js
const receivedCards = (cards) => ({
type: "RECEIVED_CARDS",
cards
})
export function getCards(param1, param2) {
// idk where you're gonna use these params btw
// also please note that fetch() isn't supported by older browsers. Here I'm showing you a simple example with axios, which basically performs the same operation. Feel free to adapt this example code as you want.
return function(dispatch) {
return axios({
url: server + "endpoint",
timeout: 20000,
method: 'get'
})
.then(function(response) {
let cards = response.data;
dispatch(receivedCards(cards));
})
.catch(function(response){
console.log(response.data.error);
})
}
};
// reducer reducer.js
const initialState = {};
export default (state = initialState, action) => {
switch(action.type) {
case "RECEIVED_CARDS":
return Object.assign({},
state,
{cards: action.cards});
default:
return state;
}
}
Related
I am trying to implement Autocomplete using materialUI and nextJs. I encountered this error whenever I start the search.
My code is like this
client:
import Head from 'next/head'
import Image from 'next/image'
import styles from '../styles/Home.module.css'
import React, {useState} from 'react'
import TextField from "#mui/material/TextField"
import Autocomplete from "#mui/material/Autocomplete"
import axios from "axios"
const getString = async (str) =>{
try{
// let searchableString = str.replace(/,/g, "")
let url = "http://localhost:4000/searchpop?search=" + str;
let { data } = await axios.get(url)
return data
} catch (error){
console.log(error);
}
}
export default function Home() {
const [searchOption, setOption] = useState([]);
searchOption.map((obj)=>{
console.log(obj.population_mesh.cui_str);
})
const onChangeOne = async (e) =>{
if(e.target.value) {
let data = await getString(e.target.value)
setOption(data);
}
}
return (
<div className={styles.container}>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<div style={{marginTop: 50}}>
<Autocomplete
freeSolo
filterOptions={(x)=> x}
onChange={(e)=> console.log(e)}
options= {searchOption ? searchOption.map((obj)=> obj.population_mesh.cui_str): []}
// options = {hello}
renderInput={(params)=>(
<TextField
{...params}
label="Search String"
onChange={(e) => onChangeOne(e)}
/>
)}
/>
</div>
</div>
)
}
I am very new to these technologies. So please help me in resolving this issue.
I also dont understand below. here is population_mesh is the field and cui_str is is subfield in the data base which i want to print for autocomplete
options= {searchOption ? searchOption.map((obj)=> obj.population_mesh.cui_str): []}
Would like to know how to implement the Wordpress Featured Image to multiple vue.js/nuxt.js based headless-CMS approaches using the Wordpress restful API.
Initially, I followed this immensely helpful tutorial headless-cms with nuxt and created a headless CMS via the wordpress api, and of course applied it to my use-case (here is a link to a live version nuxt-headless-cms-webapp. Unfortunately, I have been unable to figure out how to include a post's featured image as it is not covered in this particular tutorial. I then did a bit of research and ended up piecing together another project (vue.js), in which I was able to implement featured images. That being said I would like guidance with regard to implementing my working code in terms of the wp-featured image, to the original tutorial's project (as nuxt provides better routing and SEO options from my understanding. Thank you in advanced for any help!
First, here is the axios http request syntax found in the original tutorial (nuxt) project's index.js:
const siteURL = "https://indvillage.com"
export const state = () => ({
posts: [],
tags: []
})
export const mutations = {
updatePosts: (state, posts) => {
state.posts = posts
},
updateTags: (state, tags) => {
state.tags = tags
}
}
export const actions = {
async getPosts({ state, commit, dispatch }) {
if (state.posts.length) return
try {
let posts = await fetch(
`${siteURL}/wp-json/wp/v2/posts?_embed`
).then(res => res.json())
posts = posts
.filter(el => el.status === "publish")
.map(({ id, slug, title, excerpt, date, tags, content }) => ({
id,
slug,
title,
excerpt,
date,
tags,
content
}))
commit("updatePosts", posts)
} catch (err) {
console.log(err)
}
},
async getMedia({ state, commit }) {
if (state.media.length) return
try {
let media= await fetch(
`${siteURL}/wp-json/wp/v2/media?_embed`
).then(res => res.json())
commit("updatePosts", media)
} catch (err) {
console.log(err)
}
},
async getTags({ state, commit }) {
if (state.tags.length) return
let allTags = state.posts.reduce((acc, item) => {
return acc.concat(item.tags)
}, [])
allTags = allTags.join()
try {
let tags = await fetch(
`${siteURL}/wp-json/wp/v2/tags?page=1&per_page=40&include=${allTags}`
).then(res => res.json())
tags = tags.map(({ id, name }) => ({
id,
name
}))
commit("updateTags", tags)
} catch (err) {
console.log(err)
}
}
}
Next, we have the index.vue page where the above logic is implemented.
template>
<div>
<app-masthead></app-masthead>
<div class="posts">
<main>
<div class="post" v-for="post in sortedPosts" :key="post.id">
<h3>
<a :href="`blog/${post.slug}`">{{ post.title.rendered }}</a>
</h3>
<small>{{ post.date | dateformat }}</small>
<div v-html="post.excerpt.rendered"></div>
<a :href="`blog/${post.slug}`" class="readmore slide">Read more ⟶</a>
</div>
</main>
<!--<aside>
<h2 class="tags-title">Tags</h2>
<div class="tags-list">
<ul>
<li
#click="updateTag(tag)"
v-for="tag in tags"
:key="tag.id"
:class="[tag.id === selectedTag ? activeClass : '']"
>
<a>{{ tag.name }}</a>
<span v-if="tag.id === selectedTag">✕</span>
</li>
</ul>
</div>
</aside>-->
</div>
</div>
</template>
<script>
import AppMasthead from "#/components/AppMasthead.vue";
export default {
components: {
AppMasthead
},
data() {
return {
selectedTag: null,
activeClass: "active"
};
},
computed: {
posts() {
return this.$store.state.posts;
_embed = true;
},
tags() {
return this.$store.state.tags;
},
sortedPosts() {
if (!this.selectedTag) return this.posts;
return this.posts.filter(el => el.tags.includes(this.selectedTag));
}
},
created() {
this.$store.dispatch("getPosts");
},
methods: {
updateTag(tag) {
if (!this.selectedTag) {
this.selectedTag = tag.id;
} else {
this.selectedTag = null;
}
}
}
};
Here is a link to my project with working wordpress featured images! https://indvillage.netlify.app/
And here is the logic associated with the axious http request I used.
The question is how, do I include my logic in terms of the wp featured image to the initial nuxt tutorial without breaking things:
export default {
data() {
return {
postsUrl: "https://indvillage.com/wp-json/wp/v2/posts",
queryOptions: {
per_page: 6,
page: 1,
_embed: true
},`
posts: []
};
},
methods: {
// Get recent posts from wp
getRecentMessages() {
axios
.get(this.postsUrl, { params: this.queryOptions })
.then(response => {
this.posts = response.data;
console.log("Posts retrieved!");
})
//document.getElementById("test").id = "testing";
.catch(error => {
console.log(error);
});
},
getPostDate(date) {
return moment(date).format("111");
},
},
mounted() {
this.getRecentMessages();
}
}
Next, here is the App.vue template that displays the parsed information:
<template id="app">
<body>
<div class="row container">
<!-- looping through and displaying the array bound posts in HTML -->
<div class="col s4 m4" v-for="(post, index) in posts" :key="index" :id="'post'+index">
<div class="card" id="test">
<div class="card-image">
<!-- rendering the post's wp:featuredmedia in the image portion of the html/css card -->
<img
v-if="post._embedded['wp:featuredmedia']"
:src="post._embedded['wp:featuredmedia'][0].source_url"
/>
</div>
<!-- rendering the post.excerpt to the html/css card container -->
<div class="card-content" v-html="post.excerpt.rendered"></div>
<div class="card-action">
<!-- rendering the post title to the action portion of the html/css card -->
{{ post.title.rendered }}
</div>
</div>
</div>
</body>
</template>
Please let me know if anyone has any suggestions with regard to implementing wp:featuredmedia to the code derived from the first project/tutorial (nuxt.js)
Thanks again! Feel free to email with further questions
Just to be simple and up to a point, I want to make a request the same way I would do it with CURL or Postman's GET. For example:
curl https://www.google.com
gives
<!doctype html><html itemscope="" ... </body></html>
However, I am unable to do it with fetch, axios, request, nee...
All I want to do is to make a GET call (to https://www.google.com) in Vue.js and popup the alert(...); with a result.
How can I accomplish such a simple and a basic task ?
You can call fetch in a method.
Vue.config.devtools = false;
Vue.config.productionTip = false;
var app = new Vue({
el: '#app',
data: {
res: ""
},
methods: {
async get() {
const url = 'https://jsonplaceholder.typicode.com/todos/1';
this.res = await fetch(url).then(r => r.json());
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button #click="get">Fetch</button>
{{ res }}
</div>
I am trying to create an extension to display all the latest posts fetched from my feed using google feeds api. To implement this, I have added this code in background.js:
appAPI.ready(function() {
// Global variable to hold the toggle state of the button
var buttonState = true;
// Sets the initial browser icon
appAPI.browserAction.setResourceIcon('images/icon.png');
// Sets the tooltip for the button
appAPI.browserAction.setTitle('My Postreader Extension');
appAPI.browserAction.setPopup({
resourcePath:'html/popup.html',
height: 300,
width: 300
});});
and in popup.html,
<!DOCTYPE html><html><head><meta http-equiv="X-UA-Compatible" content="IE=edge">
<script type="text/javascript">
function crossriderMain($) {eval(appAPI.resources.get('script.js')); }</script>
</head>
<body><div id="feed"></div></body></html>
The script.js file is-
google.load("feeds", "1");
function initialize() {
var feed = new google.feeds.Feed("http://www.xxxxx.com/feed/");
feed.setNumEntries(10);
feed.load(function(result) {
if (!result.error) {
var container = document.getElementById("feed");
for (var i = 0; i < result.feed.entries.length; i++) {
var entry = result.feed.entries[i];
var div = document.createElement("div");
var link = document.createElement('a');
link.setAttribute('href', entry.link);
link.setAttribute('name', 'myanchor');
div.appendChild(document.createTextNode(entry.title));
div.appendChild(document.createElement('br'));
div.appendChild(link);
div.appendChild(document.createElement('br'));
container.appendChild(div);
}
}
});
}
google.setOnLoadCallback(initialize);
But I am unable to get desired result.The popup doesn't display anything.It just remain blank.
Since you are using a resource file for the popup's content, it's best to load the remote script from the crossriderMain function, as follows:
<!DOCTYPE html>
<html>
<head>
<!-- This meta tag is relevant only for IE -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<script type="text/javascript">
function crossriderMain($) {
appAPI.db.async.get('style-css', function(rules) {
$('<style type="text/css">').text(rules).appendTo('head');
});
appAPI.request.get({
url: 'http://www.google.com/jsapi',
onSuccess: function(code) {
$.globalEval(code);
appAPI.db.async.get('script-js', function(code) {
// runs in the context of the extension
$.globalEval(code.replace('CONTEXT','EXTN'));
// Alternatively, run in context of page DOM
$('<script type="text/javascript">').html(code.replace('CONTEXT','PAGE DOM')).appendTo('head');
});
}
});
}
</script>
</head>
<body>
<h1>Hello World</h1>
<div id="feed"></div>
</body>
</html>
[Disclaimer: I am a Crossrider employee]
I want . Auto complete text box with multiple keyword. it's from database. if I use jQuery and do operation in client side mean. If the database size is huge, it leads to some issues. I need to know how this is done on the server side and get proper result.
I have already seen this topic but the operation is done on the client side. I need it from the database directly.
<html>
<head>
<title>Testing</title>
<link href="css/jquery-ui-1.10.3.custom.css" rel="stylesheet" type="text/css" />
<style type="text/css">
.srchHilite { background: yellow; }
</style>
<script src="scripts/jquery-1.9.1.min.js" type="text/javascript"></script>
<script src="scripts/jquery-ui-1.10.3.custom.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
NewAuto();
});
function NewAuto() {
var availableTags = ["win the day", "win the heart of", "win the heart of someone"];
alert(availableTags); // alert = win the day,win the heart of,win the heart of someone
$("#tags").autocomplete({
source: function(requestObj, responseFunc) {
var matchArry = availableTags.slice(); // Copy the array
var srchTerms = $.trim(requestObj.term).split(/\s+/);
// For each search term, remove non-matches.
$.each(srchTerms, function(J, term) {
var regX = new RegExp(term, "i");
matchArry = $.map(matchArry, function(item) {
return regX.test(item) ? item : null;
});
});
// Return the match results.
responseFunc(matchArry);
},
open: function(event, ui) {
// This function provides no hooks to the results list, so we have to trust the selector, for now.
var resultsList = $("ul.ui-autocomplete > li.ui-menu-item > a");
var srchTerm = $.trim($("#tags").val()).split(/\s+/).join('|');
// Loop through the results list and highlight the terms.
resultsList.each(function() {
var jThis = $(this);
var regX = new RegExp('(' + srchTerm + ')', "ig");
var oldTxt = jThis.text();
jThis.html(oldTxt.replace(regX, '<span class="srchHilite">$1</span>'));
});
}
});
}
</script>
</head>
<body>
<div>
<label for="tags">
Multi-word search:
</label>
<input type="text" id="tags" />
</div>
</body>
</html>
take a look to Select2 it may help you.
Select2 is a jQuery based replacement for select boxes. It supports
searching, remote data sets, and infinite scrolling of results.
link
In your code, you have provided source as array. As you mentioned in comments, problem is how to get the data to source in jquery.
To make this work,
You need to do following
load jquery in header, which is you have already done.
Provid array,string or function for the source tag. [See api for
the source tag][1]
[1]: http://api.jqueryui.com/autocomplete/#option-source
In your serverside script, provid Jason encoded string.
If you check the API, you can see they have clear mentioned this.
Here is the jquery code
$(function() {
$( "#option_val" ).autocomplete({
dataType: "json",
source: 'search.php',
minLength: 1,
select: function( event, ui ) {
log( ui.item ?
"Selected: " + ui.item.value + " aka " + ui.item.id :
"Nothing selected, input was " + this.value );
}
});
});
</script>
Here is the php code, Sorry if you use differnt serverside script language.
<?php
// Create connection
$con=mysqli_connect("localhost","wordpress","password","wordpress");
// Check connection
if (mysqli_connect_errno($con))
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
$result=mysqli_query($con,"select * from wp_users");
while($row = mysqli_fetch_array($result))
{
$results[] = array('label' => $row['user_login']);
}
echo json_encode($results);
mysqli_close($con);
?>