<Link> doesn't update component using React + Redux (not a dupe) - javascript

guys, first of all, it may look like a duplicate, but I swear, I searched all over the place and all the possible solutions didn't worked for me.
The problem is the classic "When I click on a element the URL changes but the component doesn't update"
In fact, it updates, but only on the first click.
Here is my relevant code:
index.js
...
render(
<Provider store={store}>
<ConnectedRouter history={history}>
<div>
<App />
</div>
</ConnectedRouter>
</Provider>,
target
);
App component
...
const App = () => (
<BrowserRouter>
<div>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/items/:id" component={Product} />
<Route path="/items" component={Search} />
</Switch>
</div>
</BrowserRouter>
);
export default App;
Search component
...
const Search = props => (
<div>
<header>
<SearchBar />
</header>
<main>
<SearchResult />
</main>
</div>
);
export default Search;
SearchResult component
const renderItem = result => (
<div key={result.id} className="result-item">
<Link to={`/items/${result.id}`}>
...
</Link>
</div>
);
class SearchResult extends Component {
componentWillMount() {
if (!this.props.resultIsLoading && !this.props.results.items) {
const { search: term } = queryString.parse(this.props.location.search);
this.props.search(term);
}
}
render() {
if (!this.props.results.items) return <div>...</div>;
return (
<div className="container">
<div className="product-list">
{this.props.results.items.map(renderItem)}
</div>
</div>
);
}
}
const mapStateToProps = ({ results, resultIsLoading }) =>
({ results, resultIsLoading });
const mapDispatchToProps = dispatch =>
bindActionCreators({ search }, dispatch);
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(SearchResult));
When I click the , the state doesn't change, the reducer is not called and the ProductDetails component doesn't update.
I've tried a lot of possible solutions. { pure: false } on connect, pass location as a prop, remove main BrowserRouter, remove withRouter, none seems to work.
Can, please, someone give me a light on this?

Related

React.js - Functions are not valid as a React child

I am new to React.js. I can't solve the problem. I am getting this warning:
Functions are not valid as a React child. This may happen if you return a Component instead of from render. Or maybe you meant to call this function rather than return it.
App.js
`
import React from 'react';
import MovieList from './MovieList';
import SearchBar from './SearchBar';
import AddMovie from './AddMovie';
import axios from 'axios'
import { BrowserRouter as Router, Routes, Route } from "react-router-dom"
class App extends React.Component {
state = {
movies: [],
searchQuery: ""
}
async componentDidMount() {
const response = await axios.get("http://localhost:3002/movies")
this.setState({movies: response.data})
}
deleteMovie = async (movie) => {
axios.delete(`http://localhost:3002/movies/${movie.id}`)
const newMovieList = this.state.movies.filter(
m => m.id !== movie.id
)
this.setState(state => ({
movies: newMovieList
}))
}
searchMovie = (event) => {
this.setState({searchQuery: event.target.value })
}
render() {
let filteredMovies = this.state.movies.filter(
(movie) => {
return movie.name.toLowerCase().indexOf(this.state.searchQuery.toLowerCase()) !== -1
}
)
return (
<Router>
<div className="container">
<Routes>
<Route path='/' exact element={() =>(
<React.Fragment>
<div className="row">
<div className="col-lg-12">
<SearchBar const searchMovieProp={this.searchMovie()} />
</div>
</div>
<MovieList
movies={filteredMovies()}
deleteMovieProp={this.deleteMovie()}
/>
</React.Fragment>
)}>
</Route>
<Route path='/add' element={<AddMovie />} />
</Routes>
</div>
</Router>
)
}
}
export default App;
`
What am I doing wrong?
Thanks in advance.
Passing a function to a route like you did:
<Route path='/' exact element={() =>(
<React.Fragment>
<div className="row">
<div className="col-lg-12">
<SearchBar const searchMovieProp={this.searchMovie()} />
</div>
</div>
<MovieList
movies={filteredMovies()}
deleteMovieProp={this.deleteMovie()}
/>
</React.Fragment>
)}>
looks like a router v5 syntax. This is not working in v6: you should pass an element, which is different than a function producing an element. Something like this would work:
<Route path='/' exact element={(
<React.Fragment>
<div className="row">
<div className="col-lg-12">
<SearchBar const searchMovieProp={this.searchMovie()} />
</div>
</div>
<MovieList
movies={filteredMovies()}
deleteMovieProp={this.deleteMovie()}
/>
</React.Fragment>
)}>

How to pass data from a child to another a child (nested in Home page) in React?

I'm struggling to figure out how to pass the search term from ChildOne to ChildTwo (which is nested in a page). I hope all the code I provided down below will make it clear. I tried to lift up the state to the App.js component but it didn't work or maybe I didn't do it correctly. I would appreciate any help. Thanks in advance :)
Child 1:
const ChildOne = () => {
const [searhTerm, setSearchTerm] = useState("");
return(
<InputContainer>
<input
type="text"
placeholder="Find a recipe"
value={searchTerm}
onChange={(e) => {
setSearchTerm(e.target.value);
}}
/>
<SearchIcon />
</InputContainer>
)
}
Child 2:
const ChildTwo = () => {
// I want to pass the searchTerm to be used in a fetch request in this component
const apiURL = `'url' + {searchTerm}`;
return(
...
)
}
App.js
function App(){
return(
<>
<ChildOne/>
<Switch>
<Route path="/" exact component={Home}/>
<Switch/>
</>
)
}
Home.js:
const Home = () => {
return (
<>
<ChildTwo />
</>
);
};
there is several way to do that...
I suggest you use Context Api.
if you don't want to use Context Api or State management
see this example
enter link description here
import { useState } from "react";
import {
Route,
Switch,
BrowserRouter as Router,
RouterProps
} from "react-router-dom";
import ChildOne from "./ChildOne";
import Home from "./Home";
function App() {
const [value, setValue] = useState("");
return (
<>
<ChildOne setValue={setValue} />
<Router>
<Switch>
<Route path="/" exact>
<Home value={value} />
</Route>
</Switch>
</Router>
</>
);
}
export default App;

Is there a way to force update components by url changing using redux and react-router?

I'm setting up a student social network application. I am using react, redux and react router. My feed list component keep the student id from url. When i use from react router, my component do not update.
I read this article https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/guides/blocked-updates.md and tried to wrap my components in withRouter.
index.js :
ReactDOM.render(
<Provider store={store}>
<Router>
<Route path="/" component={App} />
<Route exact path="/sign/In" component={SignIn} />
<Route exact path="/sign/Up" component={SignUp} />
</Router>
</Provider>, document.getElementById('root'));
App.js :
class App extends Component {
render() {
return (
<Router id="Page" >
<div className={this.props.AppStore.Theme}>
<header>
<NavBar />
</header>
<Route exact path="/" component={HomePage} />
<Route exact path="/#:id" component={feedpage} />
</div>
</Router>
);
}
}
const mapStateToProps = (state) => {
return state
}
export default withRouter(connect(mapStateToProps)(App));
feedPage.js :
class feedPage extends Component {
componentDidMount() {
const {dispatch} = this.props;
API.requireFeed(this.props.match.params.id,"profil",20)
.then((res) => {
if(res){
dispatch(postList(res));
}
})
}
render() {
return (
<div id="Page">
<div id="mainPage">
<div id="centralCard">
{this.props.postList.map((element) => (
<div>
<Link to={'/#'+element.Pseudo}>{element.Pseudo}</Link>
<p>{element.Content}</p>
</div>
))}
</div>
</div>
</div>
);
}
}
const mapStateToProps = (state) => {
return state
}
export default withRouter(connect(mapStateToProps)(feedPage));
I expect to have update of the component each Time i click on a link to an other feedPage.
I someone have an idea about how to resolve the issue, i would be enjoing it :)
You should have just one router component (that in index.js), nested routing in your app component does not require another router, just declare your routes.

Path matches Route but the component for that route is not rendered

my component for the Route is this:
const Workout = props => {
console.log(props);
return (
<div>
<h1>hello</h1>
</div>
);
};
export default Workout;
then I import this component to my index.js
import Workout from "./views/Workout";
then I define my Route:
<Route exact path="/:weekId/:dayId:/work" component={Workout} />
I hit the route in the browser:
codesandbox.io/week-1/day-1/work
but nothing is rendered, no error and no console.log :(
The path variable should be :dayId, not :dayId:.
Example
const Workout = props => {
console.log(props);
return (
<div>
<h1>hello</h1>
</div>
);
};
function App() {
return (
<BrowserRouter>
<Route path="/:weekId/:dayId/work" component={Workout} />
</BrowserRouter>
);
}

React with Redux and Router - not rendering component

I don't understand why component Sample is not rendering at all. Url changes, no errors in console, however component is not mounted. No matter if it is functional component or React class. And why inline component with URL "/thisworks" is rendered properly. What am I doing wrong here?
index.jsx:
render(
<Provider store={store}>
<Root />
</Provider>,
document.getElementById("root")
);
root.js:
const Root = () => (
<div>
<BrowserRouter>
<Switch>
// routes below work fine
<Route path="/login" component={LoginPage} />
<Route path="/" component={App} />
</Switch>
</BrowserRouter>
<DevTools />
</div>
)
App.js:
class App extends React.Component {
render() {
return (
<div>
<NavMenu />
<Switch>
<Route path="/thisworks" render={(props) => {
return (<div>This works!</div>);
}} />
<Route path="/sample" Component={Sample} /> // not working - not rendering component Sample
<Redirect from="/" to="/sample" />
</Switch>
</div>
);
}
}
const mapStateToProps = (state, ownProps) => ({})
const mapDispatchToProps = (dispatch) => ({})
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(App))
Sample.jsx:
const Sample = (props) => {
return (
<div>
Sample!
</div>
);
}
export default Sample;
Maybe component instead of Component?
<Route path="/sample" component={Sample} />

Categories