javascript reactjs react-router react-router-v4 react-router-dom

javascript - React no vuelve a cargar los datos del componente en el cambio de parámetro de ruta o cambio de consulta



reactjs react-router (4)

Tengo un componente de "inicio" con enlaces, y cuando hace clic en un enlace, el componente del producto se carga con el producto. También tengo otro componente que siempre está visible, que muestra enlaces a los "productos visitados recientemente".

Estos enlaces no funcionan cuando se encuentra en la página de un producto. La url se actualiza cuando hago clic en el enlace y se produce un render, pero el componente del producto no se actualiza con el nuevo producto.

Ver este ejemplo: Ejemplo de códigos y cajas

Aquí están las rutas en index.js:

<BrowserRouter> <div> <Route exact path="/" render={props => <Home products={this.state.products} />} /> <Route path="/products/:product" render={props => <Product {...props} />} /> <Route path="/" render={() => <ProductHistory />} /> <Link to="/">to Home</Link> </div> </BrowserRouter>;

Los enlaces en ProductHistory se ven así:

<Link to={`/products/${product.product_id}`}> {product.name}</Link>

Por lo tanto, coinciden con la Route path="/products/:product" .

Cuando estoy en la página de un producto e intento seguir un enlace de ProductHistory, la URL se actualiza y se produce un render, pero los datos del componente no cambian. En el ejemplo de Codesandbox, puede descomentar la alerta en la función de representación de componentes del Producto para ver que se muestra cuando sigue el enlace, pero no sucede nada.

No sé cuál es el problema ... ¿Puede explicar el problema y encontrar una solución? ¡Eso seria genial!


Aunque todas las formas mencionadas funcionarán, no veo un punto para usar getDerivedStateFromProps . Según los documentos de React, "si desea volver a calcular algunos datos solo cuando cambia un accesorio, utilice en su lugar un asistente de memorización".

Aquí, en cambio, sugeriría simplemente usar componentDidUpdate junto con cambiar el Component a PureComponenet .

Con referencia a los documentos React, PureComponenet s solo PureComponenet si al menos un estado o valor de prop cambia. El cambio se determina haciendo una comparación superficial de las teclas de estado y de apoyo.

componentDidUpdate = (prevProps) => { if(this.props.match.params.id !== prevProps.match.params.id ) { // fetch the new product based and set it to the state of the component }; };

Tenga en cuenta que lo anterior solo funciona si cambia el Componente a PureComponent y, obviamente, necesita importarlo desde React.


Como el componente del Producto ya está cargado, no se volverá a cargar. Debe manejar la nueva identificación del producto en el siguiente método de componente

componentWillReceiveProps(nextProps) { if(nextProps.match.params.name.product == oldProductId){ return; }else { //fetchnewProduct and set state to reload }

Con la última versión de react (16.3.0 en adelante)

static getDerivedStateFromProps(nextProps, prevState){ if(nextProps.productID !== prevState.productID){ return { productID: nextProps.productID}; } else { return null; } } componentDidUpdate(prevProps, prevState) { if(prevProps.productID !== this.state.productID){ //fetchnewProduct and set state to reload } }


Junto con componentDidMount , también debe implementar el componentWillReceiveProps o usar getDerivedStateFromProps (desde la versión 16.0.0 en adelante) en la página de Products , ya que el mismo componente se re-rendered con params actualizados y not re-mounted cuando cambia los parámetros de ruta, esto es porque los parámetros se pasan como accesorios al componente y al cambiar los accesorios, los componentes React se vuelven a procesar y no se vuelven a montar.

EDITAR: desde la v16.3.0 use getDerivedStateFromProps para establecer / actualizar el estado en función de los accesorios (no es necesario especificarlo en dos métodos de ciclo de vida diferentes)

static getDerivedStateFromProps(nextProps, prevState) { if (nextProps.match.params.product !== prevState.currentProductId){ const currentProductId = nextProps.match.params.product const result = productlist.products.filter(obj => { return obj.id === currentProductId; }) return { product: result[0], currentId: currentProductId, result } } return null; }

Anterior v16.3.0, usarías componentWillReceiveProps

componentWillReceiveProps(nextProps) { if (nextProps.match.params.product !== this.props.match.params.product) { const currentProductId = nextProps.match.params.product const result = productlist.products.filter(obj => { return obj.id === currentProductId; }) this.setState({ product: result[0], currentId: currentProductId, result }) } }

Códigos de trabajo y caja


Si no mantiene el estado en su componente, puede usar componentDidUpdate sin la necesidad de getDerivedStateFromProps :

componentDidUpdate(prevProps) { const { match: { params: { value } } } = this.props if (prevProps.match.params.value !== value){ doSomething(this.props.match.params.value) } }