1

/keywordsActions

import { UPDATE_KEYWORDS } from "./actionTypes";
import queryString from "query-string";

const keywordsArrayFromUrl = () => {
  const query = queryString.parse(window.location.search);
  if (query.keywords) {
    const removeDuplicate = new Set(query.keywords.split(" "));
    return Array.from(removeDuplicate);
  }

  return [];
};

export function updateKeywords() {
  return async dispatch => {
    dispatch({
      type: UPDATE_KEYWORDS,
      payload: await keywordsArrayFromUrl()
    });
  };
}

/keywordReducer

import { UPDATE_KEYWORDS } from "../actions/actionTypes";

export default function(state = [], action) {
  switch (action.type) {
    case UPDATE_KEYWORDS:
      return action.payload;
    default:
      return state;
  }
}

/SearchBar -- React Component

import React, { Component } from "react";
import { withRouter } from "react-router-dom";
//Redux
import { connect } from "react-redux";
import { updateKeywords } from "../store/actions/KeywordsAction";

class Searchbar extends Component {
  constructor(props) {
    super(props);
    this.state = {
      keywords : this.props.keywords
      keywordsString: this.props.keywords.join(" ")
    };
  }

  componentDidMount() {
    this.props.updateKeywords();
    console.log(this.props)
    setTimeout(() => console.log(this.props), 10);
  }

  _handleChange = e => {
    this.setState({ keywordsString: e.target.value });
  };

  _handleSearch = value => {
    this.setState({ keywordsString: value });
    this.props.history.push(`/search?keywords=${value}`);
  };

  render() {
    return (
      <Search
        className="Searchbar"
        placeholder="Cauta prin iBac..."
        value={this.state.keywordsString}
        onChange={this._handleChange}
        onSearch={this._handleSearch}
      />
    );
  }
}

const mapStateToProps = state => {
  return {
    keywords: state.keywords
  };
};

export default connect(
  mapStateToProps,
  { updateKeywords }
)(withRouter(Searchbar));

I want to save the keywords from the Url to the store and then pass it to the Search bar state.

But i dont understand this :

  componentDidMount() {
    this.props.updateKeywords();
    console.log(this.props); // this.props.keywords is empty
    setTimeout(() => console.log(this.props), 10); // After 10 ms this.props.keywords is no empty 
  }

After 10 ms the props of Searchbar gets updated but the component doesn't render again.

Sorry for my question, I am really new to React / Redux. Please let me know what I am doing wrong. Thank you all!

Update :

  componentDidMount() {
    this.props.updateKeywords();
    setTimeout(() => {
      this.setState({
        keywordsString: this.props.keywords.join(" ")
      });
    }, 0);
  }

This code is also working... but this other is not working

componentDidMount() {
    this.props.updateKeywords();
      this.setState({
        keywordsString: this.props.keywords.join(" ")
      });
  }

1 Answers1

0

The reason is that componentDidMount is only called once on mount. What you're looking for is either componentShouldUpdate or componentDidUpdate or the render function, all of which are called when your component receives the updated state from redux. You can read here for more information on what these functions do.

https://reactjs.org/docs/react-component.html#updating

ManavM
  • 2,328
  • 2
  • 13
  • 30