How to edit react content dynamically - javascript

Ok..first things first:
Please refer the image of webApp attached:
My Application displays loginIdCard's consisting(website,username,password) from mongoDb which
i can edit from react when clicking on edit button.
What i did is initially i maintained a editMode key in component state a set it as false.
when a user clicks on edit button the LoginIdCard becomes editable and on clicking save button new values are set in component state and then editLoginId function is dispatch which updates this new value in database.
Now,
following are the things i want:
Initially when edit button is clicked, the value inside the input field should be the original values,
but now it is show empty.
2.The new values should be displayed immediately without rerendering of component.
Note: Now,after cliciking on save button , the component rerenders and the endpoint api return res data which is not a array, so the LoginDisplay component is not able to map and gives this.map is not a function error.
Please Help me
Web app rendering LoginIdCard in LoginDisplay Component
"LoginDispaly Component:Here LoginIdCard Component Will Rendender"
import React, { Component } from "react";
import { connect } from "react-redux";
import PropTypes from "prop-types";
import LoginIdCard from "./LoginIdCard";
import EditLoginIdComponent from "./EditLoginIdComponent";
import { fetchLoginIds } from "../actions/loginInIdsAction";
import "../css/displaySection.css";
class LoginsDisplay extends Component {
componentWillMount() {
this.props.fetchLoginIds();
}
render() {
const { logins } = this.props;
return (
<div className="display-section">
{logins.map((logins) => (
<LoginIdCard logins={logins} />
))}
</div>
);
}
}
function mapStateToProps(state) {
return {
logins: state.logins.logins,
};
}
LoginsDisplay.propTypes = {
logins: PropTypes.array.isRequired,
};
export default connect(mapStateToProps, { fetchLoginIds })(LoginsDisplay);
"LoginIdCard Component it will be render in LoginDispaly Component"
import React, { Component } from "react";
import { connect } from "react-redux";
import { editLoginId } from "../actions/loginInIdsAction";
import "../css/card.css";
class LoginIdCard extends Component {
constructor(props) {
super(props);
this.state = {
website: "",
username: "",
password: "",
editMode: false,
};
this.handleChange = this.handleChange.bind(this);
// this.handleSave = this.handleChange.bind(this);
}
handleChange = (fieldName, val) => {
console.log(val);
this.setState({
[fieldName]: val,
});
};
handleSave = () => {
const { website, username, password } = this.state;
const { logins } = this.props;
this.props.dispatch(editLoginId(website, username, password, logins._id));
console.log(this.state.website, username, password, logins._id);
};
render() {
const { editMode } = this.state;
const { logins } = this.props;
// const website = logins.website;
// const username = logins.username;
// const password = logins.password;
return (
<div className="card">
{editMode ? (
<input
type="text"
onChange={(e) => this.handleChange("website", e.target.value)}
value={this.state.website}
/>
) : (
<p>{this.state.website}</p>
)}
{editMode ? (
<input
type="text"
onChange={(e) => this.handleChange("username", e.target.value)}
value={this.state.username}
/>
) : (
<p>{logins.username}</p>
)}
{editMode ? (
<input
type="text"
onChange={(e) => this.handleChange("password", e.target.value)}
value={this.state.password}
/>
) : (
<p>{logins.password}</p>
)}
{editMode ? (
<button onClick={this.handleSave}>save</button>
) : (
<button onClick={() => this.handleChange("editMode", true)}>
edit
</button>
)}
</div>
);
}
}
// this.handleChange("editMode", false)
function mapStateToProps(state) {
return {
// user: state.user.users,
// cards: state.cards.cards,
logins: state.logins.logins,
};
}
// App.propTypes = {
// user: PropTypes.array.isRequired,
// };
export default connect()(LoginIdCard);
"redux action file for editing the LoginId in mongodb"
export function editLoginId(website, username, password, id) {
return function (dispatch) {
const req = {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
website: website,
username: username,
password: password,
cardId: id,
}),
};
fetch("http://localhost:9000/editLoginId", req)
.then((res) => res.json())
.then((data) =>
dispatch({
type: EDIT_LOGIN_ID,
payload: data,
})
)
.catch((err) => {
console.log(err);
<!-- begin snippet: js hide: false console: true babel: false -->
});
};
}

Related

How to render an asynchronous result (array) in a component in react?

I have been doing js for about a month now, and I am writing this program where I am using clarifai API to see which celebrity a person on the photo resembles the most.
I want to pass the output as props to Rank component to render it, but
I get the
Type error: clarifaiResults.map is not a function at App.transformResponse
Basically, the response I want to pass as props is the
const clarifaiResults = response.outputs[0].data.regions[0].data.concepts[0].name;
part that I get in console.log now
I am assuming it's because there is no output yet when the app tries to render the component, but I can't figure out what's wrong with the code. Thank you!
App.js
import React, { Component } from 'react';
import './App.css';
import SignIn from './Component/SignIn/SignIn.js';
import Register from './Component/Register/Register.js';
import Particles from 'react-particles-js';
import Logo from './Component/Logo/Logo.js';
import Navigation from './Component/Navi/Navigation.js';
import ImageLinkForm from './Component/Form/ImageLinkForm.js';
import Rank from './Component/Rank/Rank.js'
import Clarifai from 'clarifai';
import FaceRecognition from './Component/Face/FaceRecognition.js';
import FaceComparison from './Component/Comparison/FaceComparison.js';
const app = new Clarifai.App({
apiKey: 'MYSUPERSECRETKEY'
});
const initialState = {
input: "",
imageUrl: "",
results: [],
route: "SignIn",
user: {
id: "",
name: "",
email: "",
entries: 0,
joined: "",
},
};
const particleOptions = {
particles: {
number: {
value: 40,
density: {
enable: true,
value_area: 800,
},
}
}
}
class App extends Component{
constructor() {
super();
this.state = initialState;
}
transformResponse = (response) => {
const clarifaiResults = response.outputs[0].data.regions[0].data.concepts[0].name;
const results = clarifaiResults.map((ingredient) => ({
ingredients: ingredient.name,
probablitiy: ingredient.value,
}));
this.setState({results: results.celebrityName});
return {results: []};
};
onInputChange = (event) => {
this.setState({input: event.target.value});
}
onSubmit = () => {
this.setState({imageUrl: this.state.input});
app.models
.predict(
Clarifai.CELEBRITY_MODEL,
this.state.input)
.then(response => {
console.log(response.outputs[0].data.regions[0].data.concepts[0].name)
if (response) {
fetch ('http://loclhost:3000', {
method: 'post',
headers: {'Conent-Type' : 'application/json'},
body: JSON.stringify({
input: this.state.user.input
})
})
.then((response) => response.json())
.then(count => {
this.setState(Object.assign(this.state.user, {entries:count}))
})
}
this.transformResponse(response);
})
.catch(err => console.log(err));
};
;
onRouteChange = (route) => {
if (route === 'signout'){
this.setState({isSignedIn: false})
} else if (route ==='home'){
this.setState({isSignedIn: true})
}
this.setState({route: route});
}
render() {
let { isSignedIn, imageUrl, route, results} = this.state;
return (
<div className="App">
<Particles className='particles'
params={particleOptions}
/>
<Navigation isSignedIn={isSignedIn} onRouteChange={this.onRouteChange}/>
{ route ==='home'
? <div>
<Logo />
<Rank
results = {results}/>
<ImageLinkForm
onInputChange={this.onInputChange}
onSubmit={this.onSubmit}
/>
<FaceRecognition
imageUrl={imageUrl}
/>
<FaceComparison
results = {results}
/>
</div>
: (
route === 'SignIn'
? <SignIn onRouteChange={this.onRouteChange}/>
: <Register />
)
}
</div>
);
};
}
export default App;
Rank.js
import React from 'react';
const Rank = ({results}) => {
const prediction = results.map((result) => {
const {ingredients} = result;
return (
<div>
<li className="celebrityName">{ingredients}</li>
</div>
);
});
if (prediction && prediction.length>1) {
return (
<div>
<div className='white f3'>
You look a lot like...
</div>
<div className='white f1'>
{results}
</div>
</div>
);
} else {
return (
<div>
</div>
)
}
};
export default Rank;

How to pass values from a state to another component

I have two pages on my react app. One page allows you to submit a post, and the second page shows all of the posts. I need to be able to retrieve the data from the state on one page, but I am receiving an error. What am I doing wrong to display this, because I thought I could use props to gather the state from my post page.
My Display Post Page:
import React from 'react';
import './App.css';
export default class Scroll extends React.Component {
render() {
return (
<div className="flex-container">
<div className="post">
{this.props.displayPost(this.props.state.posts)}
</div>
</div>
);
}
}
My post page:
import React from 'react';
import axios from 'axios';
import './App.css';
import { post } from '../../routes/routes';
export default class PersonList extends React.Component {
state = {
title: "",
body: "",
posts: []
};
componentDidMount = () => {
this.getPost();
}
getPost = () => {
axios.get("http://localhost:5000/posts/save")
.then((response) => {
const data = response.data;
this.setState({ posts: data });
console.log("Data has been recieved")
})
.catch(() => {
alert("Error recieving data")
})
}
handleChange = (event) => {
const target = event.target;
const name = target.name;
const value = target.value;
this.setState({
[name]: value
})
};
submit = (event) => {
event.preventDefault();
const payload = {
title: this.state.title,
body: this.state.body,
}
axios({
url: 'http://localhost:5000/posts/save',
method: 'POST',
data: payload,
})
.then(() => {
console.log('Data sent to the server');
})
.catch(() => {
console.log('Internal server error');
});
};
displayPost = (posts) => {
if (!post.length) return null;
return posts.map((post, index) => {
<div key={index}>
<h3 id="post-text">{post.title}</h3>
<p id="post-text">{post.body}</p>
</div>
});
}
render() {
console.log("State ", this.state)
return (
<div className="flex-container-home">
<div className="app">
<form onSubmit={this.submit}>
<input
placeholder="title"
type="text"
name="title"
value={this.state.title}
onChange={this.handleChange}
/>
<textarea placeholder="description"
name="body"
cols="30" rows="10"
value={this.state.body}
onChange={this.handleChange}
>
</textarea>
<button>Submit</button>
</form>
</div>
</div>
)
}
}
Here is working example:
import React from "react";
export default class PersonList extends React.Component {
state = {
title: "",
body: "",
posts: [],
};
componentDidMount = () => {
this.getPost();
};
getPost = () => {
this.setState({ posts: ["post1", "post2", "post3"] });
};
displayPost = (posts) => {
if (!posts || !posts.length) return null;
return posts.map((post, index) => (
<div key={index}>
<p>{post}</p>
</div>
));
};
render() {
return (
<div className="App">
<Scroll displayPost={this.displayPost} posts={this.state.posts} />
</div>
);
}
}
class Scroll extends React.Component {
render() {
return (
<div className="post">
Posts: {this.props.displayPost(this.props.posts)}
</div>
);
}
}

createError.js:16 Uncaught (in promise) Error: Request failed with status code 400 in react

iam getting bad request when registering the user and sending the info to the database
iam using axios.post(apiurl.{username: user.username, password: user.password, email :user.email }
and storing this code in registeruser function
and then calling it when a user submits the form
code bellow for registering users
import React, { Component } from "react";
import Form from "./form";
import joi from "joi-browser";
import {registeruser} from "../http/registeruser";
class Register extends Form {
state = {
data:{
name:"", password:"", email:""},
errors:{}
}
schema={
name: joi.string().required().label("name"),
password: joi.string().required().min(5).label("Password"),
email: joi.string().required().label("Email"),
}
doSubmit = async () =>{
await registeruser(this.state.data);
}
render() {
return ( <div>
<h1>Register</h1>
<form onSubmit={this.handleSubmit}>
{this.renderInput("name","name","string")}
{this.renderInput("password","Password","password")}
{this.renderInput("email","Email","string")}
{this.renderButton("Register")}
</form>
</div>
);
}
}
export default Register;
You are calling register user function wrong. your data object is not correctly built . I have provided a skeleton here . see if it helps
import React, { Component } from "react";
import Form from "./form";
import joi from "joi-browser";
import {registeruser} from "../http/registeruser";
class Register extends Form {
state = {
data:{
name:"", password:"", email:""},errors:{}
}
schema={
name: joi.string().required().label("name"),
password: joi.string().required().min(5).label("Password"),
email: joi.string().required().label("Email"),
}
}
const handleSubmit = () => {
//validate properly here
schema={
name: joi.string().required().label("name"),
password: joi.string().required().min(5).label("Password"),
email: joi.string().required().label("Email"),
}
// build your data object properly here
await registeruser(this.state.data);
}
render() {
return ( <div>
<h1>Register</h1>
<form onSubmit={ () => this.handleSubmit() }>. // change this function so that you dont need to bind
{this.renderInput("name","name","string")}
{this.renderInput("password","Password","password")}
{this.renderInput("email","Email","string")}
{this.renderButton("Register")}
</form>
</div>
);
}
}
export default Register;
the form component is the one to handlechange and validate data
here iam going to include it
import React, { Component } from "react";
import joi from "joi-browser";
import Input from "./input";
import Select from"../select";
class Form extends Component {
state = {
data: {},
errors:{}
};
validate = ()=>{
const options = { abortEarly : false };
const results = joi.validate(this.state.data,this.schema, options )
if (!results.error) return null;
console.log(results)
const errors = {};
for (let item of results.error.details) errors[item.path[0]] = item.message;
return errors;
}
handleSubmit = e => {
e.preventDefault();
const errors = this.validate();
this.setState({ errors: errors || {} });
if (errors) return;
this.doSubmit();
};
validateProperty = ({name, value}) => {
const obj ={[name] : value};
const schema = {[name] : this.schema[name]}
const {error}= joi.validate(obj,schema);
return error ? error.details[0].message : null ;
}
handleChange = ({ currentTarget: input }) => {
const errors = { ...this.state.errors };
const errorMessage = this.validateProperty(input);
if (errorMessage) errors[input.name] = errorMessage;
else delete errors[input.name];
const data = { ...this.state.data };
data[input.name] = input.value;
this.setState({ data, errors });
};
renderButton(label) {
return <button
disabled={this.validate()}
className="btn-primary btn">{label}</button>
}
renderInput(name, label, type = "text") {
const { data, errors } = this.state;
return (
<Input
type={type}
name={name}
value={data[name]}
label={label}
onChange={this.handleChange}
error={errors[name]}
/>
);
}
renderSelect(name, label, options) {
const { data, errors } = this.state;
return (
<Select
name={name}
value={data[name]}
label={label}
options={options}
onChange={this.handleChange}
error={errors[name]}
/>
);
}
}
export default Form;

React Reducer is not updating State

I was driven crazy by my first react-redux app. My Redux State is never updated.
I tried to find every solution on the website but they are not helping. One very similar question here used promise but I am not.
Redux-dev-tools catch the actions about the login_success but the global state is never updated, please tell me what should I do to debug if you could, thank you so much.
First Index.js
import ... from ...
const compostEnhancer = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const rootReducer = combineReducers({
auth: authReducer,
})
const store = createStore(rootReducer, compostEnhancer(
applyMiddleware(thunk)
));
const app = (<BrowserRouter><App /></BrowserRouter>)
ReactDOM.render(<Provider store={store}>{app}</Provider>, document.getElementById('root'));
registerServiceWorker();
authReducer.js :
import * as actionTypes from '../actions/actionTypes';
const initialState = {
token: null,
userId: null,
error: null,
loading: false
}
const authReducer = (state = initialState, action) => {
switch (action.types) {
case actionTypes.LOGIN_START:
return {
...state,
};
case actionTypes.LOGIN_SUCCESS:
return {
...state,
token: action.idToken,
userId: action.userId,
loading: false,
error:null
}
default:
return state;
}
}
export default authReducer;
authAction.js:
import * as actionTypes from './actionTypes';
import axios from 'axios';
export const loginStart= () =>{
return {
type: actionTypes.LOGIN_START
};
}
export const loginSuccess = (token,userId) =>{
return {
type: actionTypes.LOGIN_SUCCESS,
userId: userId,
idtoken: token,
}
}
export const loginFail = (error) =>{
return {
type:actionTypes.LOGIN_FAIL,
error:error
}
}
export const auth = (email,password,isSignup ) =>{
return dispatch =>{
dispatch(loginStart());
const authData = {
email: email,
password: password,
returnSecureToken:true
}
let url = 'https://www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser?key=...'
if(!isSignup ){
url = 'https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key=...'
}
axios.post(url, authData)
.then( response =>{
console.log(response);
dispatch(loginSuccess(response.data.idToken, response.data.localId))
})
.catch(err=>{
console.log(err);
dispatch(loginFail(err));
})
}
}
Login.js (Component):
import ... from ...;
class Login extends Component {
constructor(props) {
super(props);
this.state = {
email: "",
password: "",
isSignup: false,
}
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit = e => {
e.preventDefault();
// This will trigger actions
this.props.onAuth(this.state.email, this.state.password, this.state.isSignup);
console.log(this.props.token) //here I can Get Token
}
handleChange = (e) => {
this.setState({ [e.target.name]: e.target.value });
}
render() {
let form =
<div className={classes.ContactData} >
<h4>Sign IN</h4>
<form onSubmit={this.handleSubmit} >
<Input
elementType='input'
name="email"
required
label="Email"
placeholder="Email"
value={this.state.email}
margin="normal"
onChange={this.handleChange}
/>
<br />
<Input
elementType='input'
required
name="password"
value={this.state.password}
label="Password"
onChange={this.handleChange}
/>
<br />
<Button
color="primary"
type="submit"
>Submit</Button>
<Button color="primary" href="/"> CANCLE</Button>
</form>
</div>
if (this.props.loading) {
form = <Spinner />
}
let errorMessage = null;
if (this.props.error) {
errorMessage =(
<p>{this.props.error.message} </p>
)
}
let token = null;
if(this.props.token){
token = this.props.token.toString()
}
return (
<div>
{errorMessage}
{ form }
</div>
)
}
}
const mapStateToProps = state => {
return {
loading: state.auth.loading,
error: state.auth.error,
token:state.auth.idToken,
}
}
const mapDispatchToProps = dispatch => {
return {
onAuth: (email, password, isSignup) => dispatch(actions.auth(email, password, isSignup)),
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Login);
And also, the problem leads to my Spinner and show ErrorMessage not working.
I suppose its a typo.
instead of
switch (action.types)
try this
switch (action.type)
In reducer, we get an object returned from the actions, on the argument action.

React Native Redux how can I update UI, navigate to new screen after call API that without used flag

I'm developing a mobile application by use react-native and redux,thunk and it's the first time I write by react-native.
My problem is I call an api and the response is valid, I want to do somethings as update UI, navigate to new screen... for do that I will need to used flag in my component to mark it.
This is login example, after user login success, i want to navigate to Home screen. for do that, i need check an flag isLoginSuccess in props on the method componentWillReceiveProps to know user have been login success or not, but i think it's not good solution.
My question is we have other way to do it without use flag.
action.js
export const LOGIN_SUCCESS = "LOGIN_SUCCESS";
export const LOGIN_FAIL = "LOGIN_FAIL";
export const LOGIN = "LOGIN";
export function login(username, password) {
console.log(username)
return {
type: LOGIN,
username: username,
password: password
}
}
export function loginSuccess(data) {
return {
type: LOGIN_SUCCESS,
loginData: data
}
}
export function loginFail(error) {
return {
type: LOGIN_FAIL,
error: error
}
}
export function doLogin(username, password) {
return (dispatch) => {
dispatch(login(username, password))
api.login(username, password)
.then(response => response.json())
.then(jsonData => {
console.log(jsonData)
dispatch(loginSuccess(jsonData))
})
.catch((error) => {
dispatch(loginFail(error))
})
}
}
reducer.js
const initialState = {
loginData:{},
isLoginDoing : false,
isLoginSuccess : false,
username :"",
password : "",
error : {},
}
export default function(state = initialState , action ={}){
switch(action.type){
case actionType.LOGIN:{
return {
...state,
username: action.username,
password: action.password,
isLoginDoing : true
}
}
case actionType.LOGIN_SUCCESS:{
return {
...state,
loginData: action.loginData,
isLoginDoing : false,
isLoginSuccess : true
}
}
case actionType.LOGIN_FAIL:{
return {
...state,
isLoginDoing : false,
isLoginSuccess : false,
error : action.error
}
}
default :{
return state
}
}
}
component.js
import { connect } from "react-redux"
import { bindActionCreators } from 'redux';
import { doLogin } from '../actions'
import BaseComponent from './baseComponent'
class Login extends BaseComponent {
constructor(props) {
super(props)
this.state = {
username: '',
password: '',
}
this.functionLogin = this.functionLogin.bind(this);
}
functionLogin() {
const { username, password } = this.state;
if(!this.props.loginReducer.isLoginDoing){
this.props.doLogin(username, password)
}
}
componentWillReceiveProps (nextProps) {
console.log("componentWillReceiveProps");
const { navigate, goBack } = this.props.navigation;
if(nextProps.loginReducer.isLoginSuccess){
// this._navigateTo('Home')
navigate('Home',nextProps.loginReducer.loginData);
}
}
render() {
const { navigate, goBack } = this.props.navigation;
return (
<View style={{ backgroundColor: 'color', marginTop: 10 }} >
<TextInput
style={{ height: 40 }}
placeholder="Username"
onChangeText={value => this.setState({ username: value })}
/>
<TextInput
style={{ height: 40 }}
placeholder="Password"
onChangeText={value => this.setState({ password: value })}
/>
<Button
onPress={this.functionLogin}
title="Login"
color="#841584"
/>
</View>
);
}
}
const mapStateToProps = (state) => {
console.log(state);
return {
loginReducer: state.loginReducer
};
}
function mapDispatchToProps(dispatch) {
return {
doLogin: (username, password) => dispatch(doLogin(username, password))
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Login)
Thanks
In your function doLogin, you can dispatch a navigation action after dispatch(loginSuccess(jsonData)).
For example for react-navigation (if you have integrated it with redux, if it's not the case, see https://reactnavigation.org/docs/guides/redux):
dispatch(NavigationActions.navigate({routeName: 'Home'});
(Don't forget import { NavigationActions } from 'react-navigation';)

Categories