I am try to make pagination with react-router and redux.
To simplify the situation, I removed my paginator and left only News component.
I have the same problem. When I push button Route adds to path. And path looks like 'http://localhost:3000/news/page/news/page/news/page/4'.
import React, { Component } from 'react'
import { Link } from 'react-router'
export default class News extends Component {
render() {
let nextPage = + (this.props.params.page || 1);
return(
<div>
<h1>I am on {nextPage}</h1>
<ul>
<li><Link to='news/page/2'>Page2</Link></li>
<li><Link to='news/page/3'>Page3</Link></li>
<li><Link to='news/page/4'>Page4</Link></li>
</ul>
</div>
)
}}
export const routes = (
<div>
<Route path='/' component={App}>
<IndexRoute component={Home}/>
{/*}<IndexRedirect to='list' />*/}
<Route path='/news(/page/:page)' component={News}/>
<Route path='/admin' component={Admin} onEnter={Admin.onEnter}/>
<Route path='products' component={Products}/>
<Route path='contacts' component={Contacts}/>
<Route path='about' component={About} />
<Route path='login' component={LoginPage} />
<Route path='orders' component= {Orders}/>
<Route path='signup' component={SignupPage}/>
<Route path='validateEmail' component= {requireIdentification(ValidateEmail)}/>
<Route path='/verifyEmail/:token' component={CheckEmail}/>
</Route>
<Route path='*' component={NotFound} />
</div>
)
The decision is
<li><Link to='/news/page/2'>Page2</Link></li>
instead of
<li><Link to='news/page/2'>Page2</Link></li>
Related
I am creating a list tracking app with React hooks, Redux, and Ruby on Rails. There is a List model, with a title as a string and completed as a boolean, and a ListItem model with descriptions as a string (the list item), completed boolean, and list_id as an integer.
I am using react route V6 for this and getting a little lost in re-rendering/ updating the page. Here is the breakdown of the application:
On the home screen, you can click to view all Lists and add a new list. when viewing all list each list title is displayed as a link to that list show page. The show page shows the list title, list items and a form to add another list item. Now where I am having trouble is being able to add a new list item, and it display on the page right after submission. Right now when I add a new item, and refresh the page it is not there. But if I click back to view all lists, then click that list again it shows up under the list items.
I tried using useNavigate to navigate to that list show page even though it is already on it but I am getting this error
Uncaught TypeError: Cannot destructure property 'list' of 'location.state' as it is null.
Here is all my components:
App.js
class App extends React.Component {
render(){
return (
<div className="App">
<Navbar/>
<br></br>
<Routes>
<Route path="/" element={<Home/>} />
<Route path="/lists" element={<Lists />} />
<Route path="/lists/new" element={<ListForm />} />
<Route path="/lists/:id" element={<ListContainer />} />
</Routes>
</div>
);
}
}
Lists.js
export default function Lists() {
const lists = useSelector(state => state.lists)
// replaces mapStateToProps
const dispatch = useDispatch()
// replaces mapDispatchToProps
useEffect(() => {
dispatch(fetchLists())
}, [])
return (
<div>
{Array.isArray(lists) && lists.map((list) => {
return (
<Link
key={list.id}
to={`/lists/${list.id}`}
state={{ list: list }}
>
<h2>{list.title}</h2>
</Link>
)
})}
</div>
)
}
ListContainer.js
export default function ListContainer() {
const location = useLocation();
const { list } = location.state;
console.log(list)
return (
<div>
<List list={list}/>
<ListItemForm list={list}/>
</div>
);
}
List.js
export default function List({list}) {
return (
<div>
<h4>{list.title}</h4>
{list.list_items.map((item) => {
return (
<div key={item.id}>
<li key={item.id}>{item.description}</li>
</div>
);
})}
<br></br>
</div>
);
}
and ListItemForm.js
export default function ListItemForm({list}) {
const [item, setItem] = useState("")
const dispatch = useDispatch()
const navigate = useNavigate()
function handleSubmit(e) {
e.preventDefault()
let newItem = {description: item, completed: false, list_id: list.id}
dispatch(createListItem(newItem, list.id))
setItem("")
navigate(`/lists/${list.id}`)
}
return (
<div>
<br></br>
<form onSubmit={handleSubmit}>
<label>Add to your list: </label>
<input value={item} onChange={(e) => setItem(e.target.value)} />
</form>
</div>
)
}
I have been stuck on this for quite some time now and not sure where to go from here or where I am going wrong. Any help is appreciated!!
Sometimes when you navigate to "/lists/:id" you send route state, sometimes you don't. It's undefined when you navigate to "/lists/:id" when adding new list items. This navigation to the route you are already on for editing a list is unnecessary.
Since you are using Redux I don't think there's any need to send a list item in route state at all. Use the id route parameter and your lists redux state to derive the specific list you want to view/edit.
Example
Given: <Route path="/lists/:id" element={<ListContainer />} />
Lists
function Lists() {
const dispatch = useDispatch();
const lists = useSelector((state) => state.lists);
useEffect(() => {
if (!lists.length) {
dispatch(fetchLists());
}
}, [dispatch, lists]);
return (
<div>
{lists.map((list) => (
<Link key={list.id} to={`/lists/${list.id}`}>
<h2>{list.title}</h2>
</Link>
))}
</div>
);
}
ListContainer
import { useParams } from 'react-router-dom';
function ListContainer() {
const { id } = useParams();
const lists = useSelector((state) => state.lists);
const list = lists.find((list) => list.id === id);
return (
<div>
<List list={list} />
<ListItemForm list={list} />
</div>
);
}
ListItemForm
function ListItemForm({ list }) {
const [item, setItem] = useState("");
const dispatch = useDispatch();
function handleSubmit(e) {
e.preventDefault();
dispatch(actions.createListItem(item, list.id));
setItem("");
}
return (
<div>
<br></br>
<form onSubmit={handleSubmit}>
<label>Add to your list: </label>
<input value={item} onChange={(e) => setItem(e.target.value)} />
</form>
</div>
);
}
I am using SvelteJs with svelte-spa-router.
I have my cases where I do
<script>
import Component1 from './Component1.svelte'
import Component2 from './Component2.svelte'
</script>
{#if condition}
<Component1 {...props1} />
{:else}
<Component2 {...props2} />
{/if}
Is there a better way I can do this? Can I dynamically import and render components only when condition is met?
I think what you need to do is called "Lazy loading" which is loading the component only when it needs to be rendered.
This concept can be used in svelte, you only need the <svelte:component /> and import('') function
// Component.svelte
<div>
Hello world
</div>
let's import that component dynamically
<script>
export let props = {}
export let condition = false
</script>
{#await import('./Component.svelte') then value }
<svelte:component this={value.default} {...props} />
{/await}
let's add a condition
{#if condition}
{#await import('./Component.svelte') then value }
<svelte:component this={value.default} {...props} />
{/await}
{/if}
Now the component will get imported only if the condition is met
you check this REPL
I am new in Gatsby and trying to place a image carousel on a modal. I have an array of images on Contentful and cannot map the images. I can do it outside of the modal but inside I can't reach to the array .
I tried to use different modals, different carousels but this is the best result that I can find.
These are the codes for carousel:
const CarouselUI = ({ position, handleClick, children }) => (
<Container>
{children}
<Arrow onClick={handleClick} data-position={position - 1}>{'<'}</Arrow>
<Arrow right onClick={handleClick} data-position={position + 1}>{'>'}</Arrow>
</Container>
);
const Carousel = makeCarousel(CarouselUI)
These are the codes for component
const Product = ({ node }) => {
const [showModal, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
return (
<div>
<figure>
<Link href="/">
<Image fluid={node.image.fluid} alt={node.title} />
</Link>
<figcaption onClick={handleShow}>
<h4>Quick View</h4>
</figcaption>
<p>{node.title}</p>
<p>{node.price}</p>
<Modal className={product1Style.Modal} show={showModal} onHide={handleClose}>
<section className={product1Style.modalheader}>
<h1>{node.title}</h1>
</section>
<section className={product1Style.modalcontent}>
<Modal.Body className={product1Style.row + ' ' + product1Style.center} closeButton>
<div className={product1Style.col + ' ' + product1Style.colspan3}>
<h4>{node.price}</h4>
<div>
<button>Purchase</button>
</div>
</div>
<div className={product1Style.col + ' ' + product1Style.colspan4}>
<Carousel>
{node.images.map((nod) => {
return (
<Slide>
<Image fluid={nod.images.fluid} />
</Slide>
)
})}
</Carousel>
</div>
</Modal.Body>
</section>
</Modal>
</figure>
</div>
)
}
And this is my class:
class Product1 extends React.Component {
render() {
const ProductNecklace = this.props.data.productNecklace.edges
return (
<Layout>
<section className={product1Style.lowerBody}>
<section className={product1Style.product1Necklace}>
<h3>Product1 Necklace</h3>
<div className={product1Style.productnecklaceimage}>
{ProductNecklace.map(({ node }, i) => (
<Product node={node} key={node.id} />
))}
</div>
</section>
</section>
</Layout>
)
}
}
Your nod is the image itself, it's the iterable object from node.images, you can name it however you want. Without knowing the data structure, it's impossible to figure out how the map should be, but I guess that should look like:
<Carousel>
{node.images.map(image => {
console.log(image)
return (
<Slide>
<Image fluid={image.childImageSharp.fluid} />
</Slide>
)
})}
</Carousel>
If you provide how's the GraphQL query, I will be able to infer how are the object and the arrays. Assuming that your node.images holds an array of images, inside each image you will need to access first to childImageSharp property before reaching fluid. As I said, your GraphQL query will be easier to debug. The console.log above the return statement will help you to know the nested properties.
i want to read the url in the clientProvider and then render the rest of the app but it throws this error :
: Children of must have a path or default prop, or be a <Redirect>. None found on element type [object Object]
Here are my 2 classes
App.js
<LocationProvider>
<Router basepath={process.env.PUBLIC_URL}>
<ClientProvider path="/:clientID">
<CssBaseline />
<AuthProvider>
<UserProvider>
<BusinessLog path="/" />
<VisitorLog path="visitorLog" />
<VisitorAccess path="visitorAccess" />
<DataAccess path="dataaccess" />
</UserProvider>
</AuthProvider>
</ClientProvider>
</Router>
</LocationProvider>
And the CLientProvider after reading the url
return loadingClient ? (
<div className={classes.root}>
<CircularProgress />
</div>
) : (
<ThemeProvider theme={theme}>
<ClientContext.Provider value={client}>{props.children}</ClientContext.Provider>
</ThemeProvider>
);
// instead of this
<Redirect from="/" to="/home" />
// do this
<Redirect path="/" to="/home" />
I am building an web application in which react-router is used. When i hit the url localhost:8080/user it works fine. When i hit localhost:8080/user/login it not works and console show unexpected tokken > what does it means? I could not understand the problem.
One more thing in this line of code when i changed to any other class then also its not working .
Routes.js
import React from 'react';
import UserBase from './UserBase.js';
import Dashboard from './Dashboard.js';
import Login from './Login.js';
// var ReactRouter = require('react-router');
// var Router = ReactRouter.Router;
// var Route = ReactRouter.Route;
import { Router, Route, IndexRoute, Link, IndexLink, browserHistory } from 'react-router'
var Routes = (
<Router history={browserHistory}>
<Route path="/" component={Login}/>
<Route path="user" component={UserBase}>
<IndexRoute component={Dashboard} />
<Route path="login" component={Login}/>
</Route>
</Router>
);
module.exports = Routes;
Login.js
import React from 'react';
class Login extends React.Component{
constructor(){
super();
}
render(){
return (
<div className="login">
<a className="hiddenanchor" id="signup"></a>
<a className="hiddenanchor" id="signin"></a>
<div className="login_wrapper">
<div className="animate form login_form">
<section className="login_content">
<form>
<h1>Login Form</h1>
</form>
</section>
</div>
<div id="register" className="animate form registration_form">
<section className="login_content">
<form>
<h1>Create Account</h1>
</form>
</section>
</div>
</div>
</div>
);
}
}
export default Login;
Routes js is working fine if I remove 'history={browserHistory}' means that if I use ugly url i.e. used with #. If I hit http://localhost:8080/#/user/login?_k=jtorvg is working fine then what will be the issue?
I use node server and express package to serve for every request.
var app = express();
app.use('/', express.static(path.join(__dirname, 'public')));
app.get('*', function(req, res) {
res.sendFile(path.join(__dirname + '/public/index.html'));
});
webpack.config.js
module.exports = {
entry: "./app/components/EntryPoint.js",
output: {
filename:"public/bundle.js"
},
module : {
loaders: [
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel',
query: {
presets: ['react', 'es2015']
}
}
]
}
};
Yes. I got the answer after struggling of hours a very small mistake. At index page bundle.js script path has to be changed for the url like localhost:8080/user/dashboard.
Just add <script src="/bundle.js" /> instead of <script src="bundle.js" />