I use React js on the client side and Node js on the server side and I'm new.
On the client side, I use a button and a table (I use the material-table component)
export default function UserProfile() {
const handleClick = () => {
return axios({
method: "post",
url: "/searchResult",
data: { data }
});
};
return (
<div className="App">
<button onClick={handleClick}> search <button/>
<RemoteData />
</div>
);
}
And RemoteData ...
import MaterialTable from 'material-table';
class RemoteData extends React.Component {
render() {
return (
<MaterialTable
title=""
columns={[
{ title: 'Id', field: 'id' },
]}
data={query =>
new Promise((resolve, reject) => {
let url = '/searchResult1'
fetch(url)
.then(res => res.json())
.then(result => {
resolve({
data: result.data,
})
})
})
}
/>
)
}
}
export default RemoteData;
Clicking the button sends the data from the client to the server and is processed.(To save your time, I write part of the code).
And Server side...
method.post('/searchResult1', searchResult1);
searchResult1: (req, res) => {
let query = "SELECT id FROM `information` WHERE 1=1"
db.query(query, (err, result) => {
if (err) {
res.redirect('/');
}
console.log(result)
})
}
Here we display the 'result' without any problems.
My question is: how can I update and display the 'result' in the material-table with each click of the button?
In material-table documentation you have a section called Remote Data. There is an example with a Refresh button material-ui-table-remote
The code that may interest you:
class RefreshData extends React.Component {
constructor(props) {
super(props);
this.tableRef = React.createRef();
}
render() {
return (
<MaterialTable
title="Refresh Data Preview"
tableRef={this.tableRef}
columns={[
{
title: 'Avatar',
field: 'avatar',
render: rowData => (
<img
style={{ height: 36, borderRadius: '50%' }}
src={rowData.avatar}
/>
),
},
{ title: 'Id', field: 'id' },
{ title: 'First Name', field: 'first_name' },
{ title: 'Last Name', field: 'last_name' },
]}
data={query =>
new Promise((resolve, reject) => {
let url = 'https://reqres.in/api/users?'
url += 'per_page=' + query.pageSize
url += '&page=' + (query.page + 1)
fetch(url)
.then(response => response.json())
.then(result => {
resolve({
data: result.data,
page: result.page - 1,
totalCount: result.total,
})
})
})
}
actions={[
{
icon: 'refresh',
tooltip: 'Refresh Data',
isFreeAction: true,
onClick: () => this.tableRef.current && this.tableRef.current.onQueryChange(), // This line
}
]}
/>
)
}
}
Related
i am currenty using the Clarifai API to detect faces, i also created that whenever i detect a face the numbers are moving up
see below imageurl image
however, when i click on detect, even without entering any url, the number still moves up, how can i prevent it from moving up when nothing is entered,
see my code below
FRONTEND code App.js
import React, { Component } from 'react';
import Particles from 'react-particles-js';
import FaceRecognition from './components/FaceRecognition/FaceRecognition';
import Navigation from './components/Navigation/Navigation';
import Signin from './components/Signin/Signin';
import Register from './components/Register/Register';
import Logo from './components/Logo/Logo';
import ImageLinkForm from './components/ImageLinkForm/ImageLinkForm';
import Rank from './components/Rank/Rank';
import './App.css';
const particlesOptions = {
particles: {
number: {
value: 30,
density: {
enable: true,
value_area: 800
}
}
}
}
const initialState = {
input: '',
imageUrl: '',
box: {},
route: 'signin',
isSignedIn: false,
user: {
id: '',
name: '',
email: '',
entries: 0,
joined: ''
}
}
class App extends Component {
constructor() {
super();
this.state = initialState;
}
loadUser = (data) => {
this.setState({user: {
id: data.id,
name: data.name,
email: data.email,
entries: data.entries,
joined: data.joined
}})
}
calculateFaceLocation = (data) => {
const clarifaiFace = data.outputs[0].data.regions[0].region_info.bounding_box;
const image = document.getElementById('inputimage');
const width = Number(image.width);
const height = Number(image.height);
return {
leftCol: clarifaiFace.left_col * width,
topRow: clarifaiFace.top_row * height,
rightCol: width - (clarifaiFace.right_col * width),
bottomRow: height - (clarifaiFace.bottom_row * height)
}
}
displayFaceBox = (box) => {
this.setState({box: box});
}
onInputChange = (event) => {
this.setState({input: event.target.value});
}
onButtonSubmit = () => {
this.setState({imageUrl: this.state.input});
fetch('https://ancient-sea-46547.herokuapp.com/imageurl', {
method: 'post',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
input: this.state.input
})
})
.then(response => response.json())
.then(response => {
if (response) {
fetch('https://ancient-sea-46547.herokuapp.com/image', {
method: 'put',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
id: this.state.user.id
})
})
.then(response => response.json())
.then(count => {
this.setState(Object.assign(this.state.user, { entries: count}))
})
.catch(console.log)
}
this.displayFaceBox(this.calculateFaceLocation(response))
})
.catch(err => console.log(err));
}
onRouteChange = (route) => {
if (route === 'signout') {
this.setState(initialState)
} else if (route === 'home') {
this.setState({isSignedIn: true})
}
this.setState({route: route});
}
render() {
const { isSignedIn, imageUrl, route, box } = this.state;
return (
<div className="App">
<Particles className='particles'
params={particlesOptions}
/>
<Navigation isSignedIn={isSignedIn} onRouteChange={this.onRouteChange} />
{ route === 'home'
? <div>
<Logo />
<Rank
name={this.state.user.name}
entries={this.state.user.entries}
/>
<ImageLinkForm
onInputChange={this.onInputChange}
onButtonSubmit={this.onButtonSubmit}
/>
<FaceRecognition box={box} imageUrl={imageUrl} />
</div>
: (
route === 'signin'
? <Signin loadUser={this.loadUser} onRouteChange={this.onRouteChange}/>
: <Register loadUser={this.loadUser} onRouteChange={this.onRouteChange}/>
)
}
</div>
);
}
}
export default App;
BACKEND code image.js
const Clarifai = require('clarifai');
const app = new Clarifai.App({
apiKey: '378c71a79572483d9d96c7c88cb13a7a'
});
const handleApiCall = (req, res) => {
app.models
.predict(Clarifai.FACE_DETECT_MODEL, req.body.input)
.then(data => {
res.json(data);
})
.catch(err => res.status(400).json('unable to work with API'))
}
const handleImage = (req, res, db) => {
const { id } = req.body;
db('users').where('id', '=', id)
.increment('entries', 1)
.returning('entries')
.then(entries => {
res.json(entries[0].entries)
})
.catch(err => res.status(400).json('unable to get entries'))
}
module.exports = {
handleImage,
handleApiCall
}
anything i can add to prevent it?
It seems the issue is with how you handle state object, and not with the Clarifai API. For example, instead of directly modifying the state using this.state, try using this.setState(). This way, when a value in the state object changes, the component will re-render, implying that the output will change according to the new values of the detected faces.
i figured the issue,
My frontend logic woudlnt work because I'm just returning a JSON object and not assigning any status code as such. So when i receive a JSON response you cannot say if(response) because in both the cases of success and failure you get a JSON and your if condition will always be true. So instead, i just wrapped the fetch call
with an if condition saying if(this.state.input) so that you handle the case where users cannot click on a button without entering an URL
I am getting error 404 that the API cannot be found. The Boolean in API is "auto_delete". I want to change it to true when this is referenced.
I wrote a button to reference a function that would reference this API but OnClick it will not be able to find this API apparently.
I posted first the front end file with constructor/binding, button, and function. I then put API at bottom.
Any input would help.
//FRONT END
This is the front end with button and function button references to
//CONSTRUCTOR AND BINDING FUNCTION
export default class VideoContent extends Component {
constructor(props) {
super(props);
let video = this.props.video;
let user = this.props.user;
this.state = {
fetchDuration: false,
viewed: false,
subscribed:
user &&
user.hasOwnProperty("follows") &&
user.follows.includes(video.author)
};
this.view = this.view.bind(this);
this.report = this.report.bind(this);
this.reportJ= this.reportJ.bind(this);
}
<Button
disabled={user ? !user.userId : true}
onClick={this.reportJ}
style={{ float: "right", backgroundColor: "purple" }}
>
ReportJ
</Button>
//FUNCTION
reportJ() {
const { video, user } = this.props;
confirmAlert({
title: "Confirm Objectionable Content",
message: "You Sure Fool?",
buttons: [
{
label: "Yes",
onClick: () => {
axios
.post(
inDev
? devAPI.concat("reportJ")
: baseAPI.concat("reportJ"),
{
id: video._id,
update: {
auto_delete: true
}
}
)
.then(res => {
this.setState({ changed: true });
})
.catch(error => {
console.log(error);
});
}
},
{
label: "No",
onClick: () => alert("Nevermind")
}
]
});
}
//SERVER JS File with API below
router.post("/reportJ", (req, res) => {
const { id, update } = req.body;
models.Videos.findById(id, function (err, video) {
video.auto_delete = true;
video.save((err, data) => {
if (err)
return res.json({
success: false,
error: err
});
return res.json({
success: true,
data: data
});
});
});
});
I have an array of items mapped, and when I delete an item, it deletes in the database, and if I manually refresh the page it is gone. However, I want to "re-render" the list of items, once I click the delete button. From what I can find, is I need a state change to "re-render", so I tried setting up a boolean, but It doesn't "re-render". Any suggestions on best practice to achieve this result would be helpful.
class Profile extends Component {
state = {
username: '',
movies: [],
reRender: false <---- by changing this state, I want a re-render of the component
}
getUserMovies = () => {
const token = localStorage.usertoken;
const decoded = jwt_decode(token);
axios.post('/getusermovies', {
user: decoded.username
}).then(response => {
this.setState({
username: decoded.username,
// movieName: response.data.moviename
movies: response.data
})
console.log(response.data)
}).catch(error => {
console.log(error + "err in the front end getusermovies function")
})
}
componentDidMount() {
this.getUserMovies();
}
deleteMovie = (itemId) => {
axios.post('/delete', {
movie: itemId
}).catch(err => {
console.log(err + "in the deleteMovie function in front end" + itemId)
})
this.setState(prevState => ({
reRender: !prevState.reRender <------ This is where I am calling a state.
}))
}
render() {
let movies = this.state.movies;
return (
<div className="container">
<h1>{this.state.username}'s Movies: </h1>
<div className="row">
{movies.map(item =>
<div className="profile-movies-box" >
<img src={item.movie} alt='no image' className="movies-box-img" />
<h4>{item.moviename}</h4>
<button className="movie-buttons">
<Link to={{
pathname: `/movie?movieName=${item.moviename}`,
state: { link: item.moviename }
}}>View Movie</Link>
</button>
<button
className="movie-btn"
value={item.moviename}
onClick={() => { this.deleteMovie(item.moviename) }}
>Delete Movie</button>
</div>
)}
</div>
</div>
);
}
}
export default Profile;
You need to update movies array, remove item that has been deleted
deleteMovie = (itemId) => {
axios.post('/delete', {
movie: itemId
})
.then(res => {
this.setState(prevState => ({
movies: prevState.movies.filter(m => m.id !== itemId)
}));
})
.catch(err => {
console.log(err + "in the delteMovie function in front end" + itemId)
})
}
I would recommend using async await
deleteMovie = async (itemId) => {
try {
await axios.post('/delete', {
movie: itemId
});
this.setState(prevState => ({
movies: prevState.movies.filter(m => m.id !== itemId)
}));
} catch (err) {
console.log(err + "in the delteMovie function in front end" + itemId)
}
}
I'm using a react and nodejs as backend, backend work properly I guess when I tried in postman but when trying to connect into my frontend it didnt insert the properly
here's the code in react app
class CreateChapter extends React.Component {
constructor(props){
super(props);
this.state={
// editorState: EditorState.createWithContent(convertFromRaw(JSON.parse(content))),
titleChapter: "",
editorState: EditorState.createEmpty(),
id: this.props.location.state.id,
status: '',
errorSaving: '',
saved: false
}
}
// handle editor change
onEditorStateChange = (editorState) => {
this.setState({ editorState })
}
//handle title change
onTitleChange = (event) => {
this.setState({
titleChapter: event.target.value
})
}
//load data chapter saved
loadChapterSaved = (data) => {
this.setState({
titleChapter: data.titleChapter,
editorState: data.editorState,
status: 'saved'
})
}
//load data chapter published
loadChapterPublished = (data) => {
this.setState({
titleChapter: data.titleChapter,
editorState: data.editorState,
status: 'published'
})
}
//save data
onSaveData = () => {
const convertedData = convertToRaw(this.state.editorState.getCurrentContent());
fetch('http://localhost:3001/new-chapter',{
method: 'post',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
id: this.state.id,
editorState: convertedData,
titleChapter: this.state.titleChapter,
status: this.state.status
})
})
.then(response => response.json())
.then( chapter => {
console.log(chapter)
if(chapter === 'empty input'){
this.setState({
errorSaving: 'Please fill Title Chapter and the Content'
})
}else{
this.loadChapterSaved(chapter);
}
})
}
render() {
const { classes, ...rest } = this.props;
const {editorState, id, errorSaving, saved} = this.state;
console.log('status', this.state.status)
return (
<div>
<HeaderHome/>
<div className={classNames(classes.main, classes.mainRaised)}>
<div className={classes.container}>
<div className={classes.storymargin}>
<h2 className={classes.title}>New Chapter</h2>
<Card className={classes.chaptercontainer}>
<CardContent>
<TextField
fullWidth
label=" New Chapter Title"
id="chapter-title"
onChange={this.onTitleChange}
InputProps={{
disableUnderline: true,
classes:{
input: classes.titleinput
}
}}
InputLabelProps={{
shrink: true,
className: classes.titleformlabel
}}
margin="normal"
/>
<Editor
editorState={editorState}
wrapperClassName={classes.homewrapper}
editorClassName={classes.homeeditor}
toolbarClassName={classes.toolbar}
placeholder="Begin typing..."
onEditorStateChange={this.onEditorStateChange}
/>
</CardContent>
{errorSaving ?
<div className={classes.errorSavingChap}>
{errorSaving}
</div>
:
""
}
<CardActions className={classes.displaybutton}>
<Button size="small" clor="primary" className={classes.buttonnextchap}
onClick={this.onSaveData}>
Save
</Button>
<Button size="small" clor="primary" className={classes.buttonnextchap}
onClick={this.onPublishData}>
Publish
</Button>
</CardActions>
</Card>
</div>
</div>
</div>
<div className={classes.footer}>
<Footer />
</div>
</div>
);
} }
export default withStyles(createStoryStyle)(CreateChapter);
the problem is this.state.status didnt send to the backend properly, it always receives initial state which is null. I think it has something to do with how setState is asynchronous, but I'm not quite sure. When I tried it in postman, it does work.
here's my backend
app.post('/new-chapter', (req, res) => {
const { id, titleChapter, editorState, status } = req.body;
if(titleChapter === '' || editorState === ''){
db('story').where('id_user', '=', id)
.increment('chapter', 0)
.returning('chapter')
.then( chapter => {
res.json('empty input')
})
.catch( err => res.json('cannot add chapter'))
}else{
db('story').where('id_user', '=', id)
.increment('chapter', 1)
.returning('chapter')
.then( chapter => {
db.select('entry').from('story').where('id_user', '=',id)
.then( newChap => {
const chapterEntry = newChap[newChap.length - 1].entry;
db('chapter').where('id_user', '=', id)
.returning('*')
.insert({
chapter: chapter[0],
titlechapter: titleChapter,
content: editorState,
id_user: id,
status: status,
entry: chapterEntry,
})
.then( newChapter => {
res.json(newChapter[0])
})
.catch( err => res.json('cannot add new chapter'))
}
)
})
.catch( err => res.json('cannot add new chapter'))
}
})
I'm sourcing the image on aws and when I run the code through i get warning error that source.uri is null and the image wont display. Im getting the image from the server cause i can see the image in the debugger but it wont display in the code.
This is my action file src/actions/item.js
import { HOST } from '../constants';
import { normalizeItems, normalizeItem } from '../utils';
export const SET_ITEMS = 'SET_ITEMS';
export function setItems(items) {
return {
type: SET_ITEMS,
items
}
}
export function getItems() {
return (dispatch, getState) => {
return fetch(`${HOST}/api/v1/items`)
.then(response => response.json())
.then(json => {
console.log("getItems", json);
if (json.is_success) {
dispatch(setItems(normalizeItems(json.items)));
} else {
alert(json.error);
}
})
.catch(e => alert(e));
}
}
This the image of the debugger shows the i have the image there
This is my reducers file src/reducers/item.js
import { SET_ITEMS,SET_ITEM } from '../actions/item';
const initialState = {
items: [],
};
export default function(state = initialState, action) {
if (action.type === SET_ITEMS) {
return {
...state,
items: action.items
}
}
This file where i render my code src/components/MainScreen/ExploreTab.js
class ExploreTab extends Component {
componentWillMount() {
this.props.getItems();
}
onPress(item) {
this.props.navigate({ routeName: "Item", params: { item: item } });
}
render() {
const { items, filter } = this.props;
return (
<FlatList
style={styles.container}
data = { items }
renderItem={({item}) =>
<TouchableOpacity onPress={() => this.onPress(item)} style={styles.item}>
<Image style={styles.image} source = {{uri: item.image}} />
<Text style = {styles.title}>{`$${item.price} ${item.instant ? '🎉 ' : ''}${item.title}`}</Text>
<Text>{`${item.itemCategory} - ${item.itemCondition} `}</Text>
</TouchableOpacity>
}
keyExtractor={(item, index) => item.id}
/>
);
}
}
const mapStateToProps = state => ({
items: state.item.items
});
const mapDispatchToProps = dispatch => ({
navigate: (route) => dispatch(navigate(route)),
getItems: () => dispatch(getItems()),
});
if I change this line
<Image style={styles.image} source = {{uri: item.image}} />
to this I will see the image
<Image style={styles.image} source = {{uri: 'https://s3.us-east-2.amazonaws.com/borroup/photos/images/1/medium/Screen_Shot_2018-03-22_at_10.48.28_PM.png'}} />
In the src/utils/index.js
I had setup as
import { HOST } from '../constants';
export function normalizeItems(items) {
return items.map(item => {
return{
id: item.id || '',
title: item.item_name ||'',
image: `${HOST}${item.image}` ||'',
itemCategory: item.item_category ||'',
itemCondition: item.item_condition ||'',
price: item.price ||'',
instant: item.instant ||'',
}
})
}
so i had to change
image: `${HOST}${item.image}` ||'',
to this and worked for me
image: `${item.image}` ||'',