I want to upload and read some text files in my app. I have [file, setFile] in my App.js . I want to upload a file from homepage.js and keep it in the file. When I want to check file in homepage.js with console.log(file) I see null:
I need some help about that. If you need more info about code just ket me know. Thanks.
Here is my App.js file:
function App() {
const [file, setFile] = React.useState(null);
const [convertedFile, setConvertedFile] = React.useState(null);
return (
<div className="App">
<Router>
<Routes>
<Route path="/" element={<Homepage file={file} setFile={setFile} />} />
<Route path="convert" element={<Convert file={file} setConvertedFile={setConvertedFile}/>} />
<Route path="download" element={<Download convertedFile={convertedFile}/>} />
</Routes>
</Router>
</div>
);
}
Here is my homepage.js file:
function Homepage(props) {
const handleSubmit = (e) => {
e.preventDefault();
props.setFile(document.getElementById("file").files[0]);
console.log(props.file);
}
return (
<div>
<Container>
<Row style={{marginTop:"15vh"}}>
<Col>
<h1>Homepage</h1>
</Col>
</Row>
<Row style={{marginTop:"10vh"}}>
<Col>
<p style={{border:'1px solid black'}}>This tool fixes Turkish character issue on your subtitle files</p>
<div>
<Form >
<Form.Group className="mb-3">
<Form.Label>Upload your file</Form.Label>
<Form.Control id="file" type="file" />
</Form.Group>
<Button onClick={handleSubmit} variant="primary" type="submit">Submit</Button>
</Form>
</div>
</Col>
</Row>
</Container>
</div>
)
Here is my convert.js file:
function Convert(props) {
console.log(props.file);
return (
<div>
<Container>
<Row style={{marginTop:"15vh"}}>
<Col>
<h1>Converting...</h1>
</Col>
</Row>
<Row style={{marginTop:"10vh"}}>
<Col>
<ProgressBar animated now={100} />
<div id="file">
aa
</div>
</Col>
</Row>
</Container>
</div>
)
}
I solved the problem myself. It was about sync code. When I try to console.log(props.file) actually there is a props.file const in my App.js but because of the execution time It seems null. Because as I understand js starts executing the next code line before current line execution ends. Actually props.file gets the value that I want but js logs it before the assignment. I used await and fixed it
Related
I'm having issues with React using JSON server, my edit buttons adds a new item when it's supposed to edit the current item and the new item link does not work, it should open a form (the same the edit button opens) and when I hit save it should save to the array the new item. Any ideas please?
I have omitted all the imports to save space. This is App.js
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />}>
<Route index element={<h1>Welcome</h1>} />
<Route path="products" element={<ProductsList />}>
<Route index element={<p>Select a Product for more details</p>}/>
<Route path="new" element={<ProductForm />} />
<Route path=":productId/edit" element={<ProductForm />} />
<Route path=":productId" element={<Product />} />
<Route path="*" element={<h1>Product Not Found</h1>} />
</Route>
</Route>
<Route path="*" element={<h1>Page Not Found</h1>} />
</Routes>
</BrowserRouter>
);
}
export default App;
This is Home.js
function Home() {
return (
<>
<Navbar bg="dark" variant="dark">
<Container>
<Nav className="me-auto">
<Link to="/" className="nav-link">Home</Link>
<Link to="/products" className="nav-link">Products</Link>
<Link to="/newProduct" className="nav-link">New Product</Link>
</Nav>
</Container>
</Navbar>
<Stack gap={3} className="col-md-10 mx-auto mt-3">
<Outlet />
</Stack>
</>
)
}
export default Home
This is ProductForm.js
function ProductForm() {
let [product, setProduct] = useState({
id: "",
productName: "",
description: "",
price: "",
});
let { getProduct, addProduct, updateProduct } = useContext(ProductContext);
let navigate = useNavigate();
let { id, productName, description, price } = product;
useEffect(() => {
if (id === undefined) return;
async function fetch() {
await getProduct(id).then((product) => setProduct(product));
}
fetch();
}, [id]);
function handleChange(event) {
setProduct((preValue) => {
return { ...preValue, [event.target.name]: event.target.value };
});
}
function addOrUpdate() {
if (id === undefined) {
return addProduct(product);
} else {
return updateProduct(product);
}
}
function handleSubmit(event) {
event.preventDefault();
addProduct(product).then((product) => navigate(`/products/${product.id}`));
}
return (
<Form onSubmit={handleSubmit}>
<Form.Group className="mb-3">
<Form.Label>Name</Form.Label>
<Form.Control
type="text"
name="productName"
value={product.name}
onChange={handleChange}
/>
</Form.Group>
<Form.Group className="mb-3">
<Form.Label>Description</Form.Label>
<Form.Control
type="text"
name="description"
value={product.description}
onChange={handleChange}
/>
</Form.Group>
<Form.Group className="mb-3">
<Form.Label>Price</Form.Label>
<Form.Control
type="text"
name="price"
value={product.price}
onChange={handleChange}
/>
</Form.Group>
<Form.Group className="mb-3"></Form.Group>
<Button type="submit">Save</Button>
</Form>
);
}
export default ProductForm;
Link to new product should be as route ‘products/new’ unless your redirecting it somewhere
Your handle submit on form always calls addProduct not addOrUpdate
I am using React Bootstrap and Modal.
I want the Modal to open, and behind it is the window that I was in (i.e. to have the background behind the Modal to be transparent).
When I am currently getting is, when I click on the link the Modal opens in a new page with empty background.
ie.
<<<<<<<<< Current screenshot >>>>>>>>>>>>>>
What I want to achieve is something similar to the following, were the background behind the Modal is transparent:
ie.
<<<<<<<<< Desired screenshot >>>>>>>>>>>>>>
Here is my code:
<Modal.Dialog>
<Modal.Header>
<Modal.Title>New Component</Modal.Title>
<Button variant="light">X</Button>
</Modal.Header>
<Modal.Body>
<h5 className="mb-4">Component information</h5>
<Form >
<FormGroup>
<Row>
<Col md={6} className="mb-3">
<Form.Label>Name</Form.Label>
<Form.Control required type="text" placeholder="Component Name" />
</Col>
<Col md={6} className="mb-3">
<Form.Label>Quantity</Form.Label>
<Form.Control required type="number" placeholder="Quantity" />
</Col>
</Row>
</FormGroup>
</Form>
</Modal.Body>
</Modal.Dialog>
Here is the routing part, where I am linking the page to a route:
Routing:
<Switch>
<Router>
<Route exact path="/app/new" component={NewComponentForm}/>
</Router>
</Switch>
import React, { useState } from "react";
import {
Button,
Col,
Container,
Form,
FormGroup,
Modal,
Row,
} from "react-bootstrap";
import "./styles.css";
function App() {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
return (
<Container>
<Row className="justify-content-md-center align-items-center">
<Button
className="d-flex justify-content-center"
variant="primary"
onClick={handleShow}
>
Launch demo modal
</Button>
<Modal show={show} onHide={handleClose}>
<Modal.Header>
<Modal.Title>New Component</Modal.Title>
<Button variant="light" onClick={handleClose}>
X
</Button>
</Modal.Header>
<Modal.Body>
<h5 className="mb-4">Component information</h5>
<Form>
<FormGroup>
<Row>
<Col md={6} className="mb-3">
<Form.Label>Name</Form.Label>
<Form.Control
required
type="text"
placeholder="Component Name"
/>
</Col>
<Col md={6} className="mb-3">
<Form.Label>Quantity</Form.Label>
<Form.Control
required
type="number"
placeholder="Quantity"
/>
</Col>
</Row>
</FormGroup>
</Form>
</Modal.Body>
</Modal>
</Row>
</Container>
);
}
export default App;
There is a codesandbox
I am using passport.js and jwt token to handle the user authentication state in my react app. After the user logs-in, I store the token in localStorage and so depending on whether there's a token or not in the localStorage, I will updated the isAuthenticated state property.
Now, when a guest user (non-authenticated) user, opens the app, he should not be able to access the home-page of the app.
So I devided the routes that the guest user can access and the authenticated user can access to two different variable guestLinks and authLinks.
And depending on the isAuthenticated property, I will display one of those.
App.js
class App extends Component {
render() {
const authLinks = (
<Switch>
<Route
exact
path="/"
name="Login Page"
render={props => <Login {...props} />}
/>
<Route
exact
path="/404"
name="Page 404"
render={props => <Page404 {...props} />}
/>
<Route
exact
path="/500"
name="Page 500"
render={props => <Page500 {...props} />}
/>
<Route
path="/home"
name="Home"
render={props => <DefaultLayout {...props} />}
/>
</Switch>
);
const guestLinks = (
<Switch>
<Route
exact
path="/"
name="Login Page"
render={props => <Login {...props} />}
/>
<Route
exact
path="/register"
name="Register Page"
render={props => <Register {...props} />}
/>
<Route
exact
path="/404"
name="Page 404"
render={props => <Page404 {...props} />}
/>
<Route
exact
path="/500"
name="Page 500"
render={props => <Page500 {...props} />}
/>
</Switch>
);
const currentState = store.getState();
console.log(
"currentState.auth.isAuthenticated: ",
currentState.auth.isAuthenticated
);
return (
<Provider store={store}>
<HashRouter>
<React.Suspense fallback={loading()}>
{console.log(currentState.auth.isAuthenticated)}
{/* TODO: Not sure if this always works. If after the user logsin he gets a blank page and he has to reload to be redirected to home then
this way of routing may need to modified */}
{currentState.auth.isAuthenticated ? authLinks : guestLinks}
</React.Suspense>
</HashRouter>
</Provider>
);
}
}
Notice this line:
{currentState.auth.isAuthenticated ? authLinks : guestLinks}
So after the user logs in, (so he is authenticated), he is redirected to the home-page:
class Login extends Component {
constructor() {
super();
this.state = {
email: "",
mot_de_passe: "",
errors: ""
};
this.onChange = this.onChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
}
componentDidMount() {
// If the user has already logged-in and he attempts to access the login page this will redirect him to home
if (this.props.auth.isAuthenticated) {
this.props.history.push("/home");
}
}
//This runs when the component receives new properties
componentWillReceiveProps(nextProps) {
// After the user has logged-in this will redirect him to home
if (nextProps.auth.isAuthenticated) {
this.props.history.push("/home");
}
if (nextProps.errors) {
this.setState({ errors: nextProps });
}
}
onChange(e) {
this.setState({
[e.target.name]: e.target.value
});
}
onSubmit(e) {
console.log(e);
// Since it's a form, we don't want it to have its default behavior
e.preventDefault();
const userInfo = {
email: this.state.email,
password: this.state.mot_de_passe
};
// Any action that we bring-in is going to be stored inside props
//this.props.loginUser(userInfo, this.props.history);
this.props.loginUser(userInfo);
}
render() {
return (
<div className="app flex-row align-items-center">
<Container>
<Row className="justify-content-center">
<Col md="8">
<CardGroup>
<Card className="p-4">
<CardBody>
<Form noValidate onSubmit={this.onSubmit}>
<h1>Se connecter</h1>
<p className="text-muted">
Connectez-vous à votre compte
</p>
<InputGroup className="mb-3">
<InputGroupAddon addonType="prepend">
<InputGroupText>
<i className="icon-user"></i>
</InputGroupText>
</InputGroupAddon>
{/* WORK_HERE */}
<Input
name="email"
type="text"
placeholder="Email"
value={this.state.email}
onChange={this.onChange}
/>
</InputGroup>
<InputGroup className="mb-4">
<InputGroupAddon addonType="prepend">
<InputGroupText>
<i className="icon-lock"></i>
</InputGroupText>
</InputGroupAddon>
<Input
name="mot_de_passe"
type="password"
placeholder="Mot de passe"
autoComplete="current-password"
value={this.state.mot_de_passe}
onChange={this.onChange}
/>
</InputGroup>
<Row>
<Col xs="6">
<Button color="primary" className="px-4">
Se connecter
</Button>
</Col>
<Col xs="6" className="text-right">
<Button color="link" className="px-0">
Mot de passe oubliée?
</Button>
</Col>
</Row>
</Form>
</CardBody>
</Card>
<Card
className="text-white bg-primary py-5 d-md-down-none"
style={{ width: "44%" }}
>
<CardBody className="text-center">
<div>
<h2>Bienvenue au Viwone SAV</h2>
<p>
Suivez en temps réel l'évolution des opérations du
service après-vente.
</p>
</div>
</CardBody>
</Card>
</CardGroup>
</Col>
</Row>
</Container>
</div>
);
}
}
The problem is that after he logs-in, he get a blank screen and he has to reload the page in order for the home-page to be successfully displayed.
It seems that the authLinks don't get loaded fast enough for the app to be able to detect the link to the home screen.
In your App.js, get isAuthenticated value using connect() so it will re-render with latest value of isAuthencticated after login and your will see the updated urls
I didn't know the best way to describe this issue, but I'm going to try and explain as best I can.
In my core React App component, i'm doing a conditional render, based on if a user is logged in.
If Logged In --- I show the main page, and if not, they get the login screen.
On my login page, i'm trying to put in a link at the bottom which directs a user to signup for a new account. My issue that when I click to this 'newuser' page, it is rendering both my login form and the create user form, both different components (see below).
I suspect this is an issue with how I have my react router setup, but I'm not sure what the problem is.
Here is the code in my App component.
<Container>
<Router>
<Notification />
{props.loggedUser ? (
<div>
<Navbar />
<Route exact path="/" render={() => <Blogs />} />
<Route exact path="/blogs" render={() => <Blogs />} />
<Route path="/login" render={() => <Login />} />
<Route
exact
path="/blogs/:id"
render={({ match }) => (
<Blog
blog={blogById(match.params.id)}
user={props.loggedUser}
/>
)}
/>
<Route exact path="/users" render={() => <Users />} />
<Route
exact
path="/users/:id"
render={({ match }) => <User user={userById(match.params.id)} />}
/>
</div>
) : (
<>
<Login />
</>
)}
</Router>
<div>
<br />
<em>Blog app, John 2019</em>
</div>
</Container>
And here is my Login component. I've tried including the route for the new users page on both sides of the conditional statement above and then also in the Login Form below, as I have now. All are leading to the same issue.
<h1>Login To Blog Application</h1>
<Form onSubmit={handleLogin}>
<Form.Field>
<label>username</label>
<input {...username.omitreset} name="username" />
</Form.Field>
<Form.Field>
<label>password</label>
<input {...password.omitreset} type="password" />
</Form.Field>
<Button type="submit">login</Button>
<div>
<br />
<Link to="/newuser">or signup to become a new user</Link>
<Route path="/newuser" render={() => <NewUser />} />
</div>
</Form>
</>
and NewUser component
import React from "react";
import { connect } from "react-redux";
import { createUser } from "../reducers/userReducer";
import { setNotification } from "../reducers/notificationReducer";
import { Form, Button } from "semantic-ui-react";
const NewUser = props => {
const addUser = event => {
event.preventDefault();
const userObject = {
username: event.target.username.value,
name: event.target.name.value,
password: event.target.password.value
};
event.target.username.value = "";
event.target.name.value = "";
event.target.password.value = "";
props.createUser(userObject);
};
return (
<>
<h1>Create a New Blog Account</h1>
<Form onSubmit={addUser}>
<Form.Field>
<label>username</label>
<input {...props.username} name="username" />
</Form.Field>
<Form.Field>
<label>name</label>
<input {...props.name} type="password" />
</Form.Field>
<Form.Field>
<label>password</label>
<input {...props.password} type="password" />
</Form.Field>
<Button type="submit">login</Button>
</Form>
</>
);
};
const mapDispatchToProps = {
createUser,
setNotification
};
export default connect(null, mapDispatchToProps)(NewUser);
you shouldn't do conditional rendering, because when the user is not logged the Loggin component is rendered and is not depended on the path at all. then you change the path by clicking Link to="/newuser" and the Sign up renders inside
I got this working based on det2dachoppa's recommendations. Removed the conditional and added the Switch and redirects to ensure that a user can't view the pages without logging in.
<Router>
<Notification />
<div>
<Navbar />
<Switch>
{props.loggedUser && (
<React.Fragment>
<Route exact path="/">
<Blogs />
</Route>
</React.Fragment>
)}
{props.loggedUser && (
<React.Fragment>
<Route exact path="/blogs">
<Blogs />
</Route>
</React.Fragment>
)}
{props.loggedUser && (
<React.Fragment>
<Route
exact
path="/blogs/:id"
render={({ match }) => (
<Blog
blog={blogById(match.params.id)}
user={props.loggedUser}
history={props.history}
/>
)}
/>
</React.Fragment>
)}
{props.loggedUser && (
<React.Fragment>
<Route exact path="/users">
<Users />
</Route>
</React.Fragment>
)}
{props.loggedUser && (
<React.Fragment>
<Route
exact
path="/users:id "
render={({ match }) => (
<User user={userById(match.params.id)} />
)}
/>
</React.Fragment>
)}
{props.loggedUser && (
<React.Fragment>
<Route exact path="/newblog">
<NewBlog />
</Route>
</React.Fragment>
)}
<Route path="/login">
<Login />
</Route>
<Route path="/newuser">
<NewUser />
</Route>
<Redirect to="/login">
<Login />
</Redirect>
</Switch>
</div>
</Router>
I'm trying to pass information from one component to another via props in ReactJS. I'm trying to access the inside of an array that has a string of information (picture included), and then I'm trying to get that information accessible to my return() function in the component so I can use it in a modal.
This is the component that I passed the props into:
class OfferActionPreviewModal extends Component {
constructor(props) {
super(props);
this.state = {
success: false,
action: [],
offerActions: []
};
this.toggleSuccess = this.toggleSuccess.bind(this);
}
toggleSuccess() {
this.setState({
success: !this.state.success
});
}
componentDidMount() {
this.renderAdvertiserForm();
}
renderAdvertiserForm = () => {
const {
offerAction,
offerActionTriggers,
triggers,
offer
} = this.props;
console.log(offerActionTriggers);
return (
<form>
<ModalHeader toggle={this.toggleSuccess}>
{offerAction.name} - <em>{offerAction.id}</em>
</ModalHeader>
<ModalBody>
<div>
<Row>
<Col lg={6}>
<Label>Post Name</Label>
<Field
name='offerActions.name'
type='text'
component={renderField}
/>
</Col>
<Col lg={6}>
<Label>Post Method</Label>
{offerAction.postMethod}
</Col>
</Row>
<br />
<Row>
<Col lg={12}>
<Label>URL</Label>
{offerAction.url}
</Col>
</Row>
<br />
</div>
<br />
</ModalBody>
</form>
);
};
render() {
return (
<div className='animated'>
<Modal
isOpen={this.state.success}
toggle={this.toggleSuccess}
className='modal-info'
>
{this.renderAdvertiserForm()}
</Modal>
</div>
);
}
}
export default connect()(OfferActionPreviewModal);
I'm trying to access inside the OfferActionTriggers, to the OfferActionCriteria part of the object, and I've included an image of the object for reference.
Thanks for all help in advance.
You can use Nested Object Destructuring for this purpose like this
const {offerAction:{OfferActionCriteria,offerActionPost:{url,name,id,postMethod}}} =
this.props; to access the OfferActionCriteria object. inside renderAdvertiserForm function.
renderAdvertiserForm = () => {
const {offerAction:{OfferActionCriteria,offerActionPost:{url,name,id,postMethod}}} = this.props;
console.log(OfferActionCriteria);
return (
<form>
<ModalHeader toggle={this.toggleSuccess}>
{name} - <em>{id}</em>
</ModalHeader>
<ModalBody>
<div>
<Row>
<Col lg={6}>
<Label>Post Name</Label>
<Field
name='name'
type='text'
component={renderField}
/>
</Col>
<Col lg={6}>
<Label>Post Method</Label>
{postMethod}
</Col>
</Row>
<br />
<Row>
<Col lg={12}>
<Label>URL</Label>
{offerAction.url}
</Col>
</Row>
<br />
</div>
<br />
</ModalBody>
</form>
);
};