I want to repopulate the editor's state with the values i have saved to Firebase.
OnSubmit:
sendNotes = (e) => {
e.preventDefault();
let contentState = this.state.editorState.getCurrentContent()
let note = { content: convertToRaw(contentState) }
note["content"] = JSON.stringify(note.content);
this.props.createNote(note.content);
};
NoteAction:
export function getNote() {
return (dispatch) => {
database.on("value", (snapshot) => {
dispatch({
type: LOAD_NOTE,
payload: snapshot.val(),
});
});
};
}
noteReducer:
export default function (state = {}, action) {
switch (action.type) {
case LOAD_NOTE:
return action.payload;
default:
return state;
}
}
REDUX/firebase:
{
type: 'LOAD_NOTE',
payload: {
'-MNOwBIWNqY_ZFDO4ILs': '{"blocks":[{"key":"c27el","text":"ASD!!!!!!!!!!!!","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}}],"entityMap":{}}',
'-MNOyHLvaORxEmuuJmzJ': '{"blocks":[{"key":"c27el","text":"HELLO WORLD","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}}],"entityMap":{}}',
'-MNOyP50oGHRLiP3T5_h': '{"blocks":[{"key":"c27el","text":"This is a REDUX STORE","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}}],"entityMap":{}}'
}
}
MapStateToProps:
function mapStateToProps(state, ownProps) {
return {
note: state.notes,
};
}
export default connect(mapStateToProps, { getNote })(TextEditor);
My Code:
componentDidMount() {
this.props.getNote();
}
componentWillReceiveProps = (nextProps) => {
if (nextProps.note !== null) {
let item = "";
_.map(nextProps.note, (note, key) => {
return (item = note);
});
this.setState({
editorState: EditorState.createWithContent(convertFromRaw(JSON.parse(item))),
});
}
};
The code is working but I'm not 100% sure about these lifecycle methods & if the code i have written is 'stable'. I am stuck with this, please :).
Related
Hey everyone I need to change the value of a boolean in an array in react redux. In the default state it is set to false and I need to set it to true. I am trying to change the state with an onclick event but I cant seem to do it any help I would be happy. When I click on the button reserved it still set to false and I need it set to true so I can make changes.
here it is at the start
`
export const getRockets = createAsyncThunk(
'rocketSlice/getRockets',
async () => {
const response = await fetch('https://api.spacexdata.com/v3/rockets').then(
(data) => data.json()
);
const rocketApiInfo = response.map((rocket) => {
const rockets = {
id: rocket.rocket_id,
rocketName: rocket.rocket_name,
description: rocket.description,
flickrImages: rocket.flickr_images,
reserved: false,
};
return rockets;
});
return rocketApiInfo;
}
);
my reducers
const rocketsSlice = createSlice({
name: 'rockets',
initialState: {
rockets: [],
status: '',
loading: true,
},
reducers: {
reserveRocket(state, action) {
const newState = state.rockets.map((rocket) => {
if (rocket.id === action.payload) {
return { ...rocket, reserved: true };
}
return rocket;
});
return { ...state, rockets: newState };
},
cancelReservation(state, action) {
const newState = state.rockets.map((rocket) => {
if (rocket.id === action.payload) {
return { ...rocket, reserved: false };
}
return rocket;
});
return { ...state, rockets: newState };
},
},
`
the function
const reservedhandler = (e) => {
if (reserved === false) {
dispatch(reserveRocket(e.target.id));
} else {
dispatch(cancelReservation(e.target.id));
}
};
reserved is undefined so maybe that is the problem. But i am not sure how to fix it. Thanks guys
I just started using NextJS for the first time and I'm trying to use it with Redux.
I have been able to set up the redux and set up the getServerSideProps function in index.js.
The problem however is that the store returns an empty state even after I have fetched the data. When I console.log the fetched data from inside the getServerSideProps function, I see it in my terminal, so I'm left to suspect that the problem is that my action creator is not dispatching the data to the store. I even tried to handle the data fetching and dispatch from inside the action creator using redux-thunk, but that also did not work. Please I really need some help with this.
My action creator:
export const initializeArticles = (articles) => {
return {
type: 'INITARTICLES',
data: articles
}
}
My reducer:
const articlesReducer = (state = initialState, action) => {
switch (action.type) {
case 'INITARTICLES':
return action.data
case 'ADDARTICLE':
return state.concat(action.data)
case 'INCREMENTARTICLELIKES':
return state.map((article) => {
if(article.id === action.id) {
return {
...article,
likes: article.likes + 1
}
} else {
return article
}
})
case 'DELETEARTICLE':
return state.filter(article => article.id !== action.id)
case 'ADDCOMMENT':
return state.map((article) => {
if (article.id === action.id) {
return {
...article,
comments: article.comments.concat(action.data)
}
} else {
return article
}
})
case 'APPROVECOMMENT':
return state.map((article) => {
if (article.id === action.articleId) {
return article.commentIsApproved = true
} else {
return article.commentIsApproved = false
}
})
default:
return state
}
}
export default articlesReducer
My store setup:
let store;
const initstore = (initialState) => {
return createStore(
rootReducer,
initialState,
composeWithDevTools(applyMiddleware(thunk))
)
}
export const initializeStore = (preloadedState) => {
let _store = store ?? initstore(preloadedState)
if (preloadedState && store) {
_store = initstore({
...store.getState(),
...preloadedState
})
store = undefined
}
if(typeof window === 'undefined') return _store
if(!store) store = _store
return _store
}
export function useStore(initialState) {
const store = useMemo(() => initializeStore(initialState), [initialState])
return store
}
My getServerSideProps function:
export const getServerSideProps = () => {
const reduxStore = initializeStore()
const { dispatch } = reduxStore
getPosts().then((posts) => {
console.log(posts)
dispatch(initializeArticles(posts))
})
return { props: { initialReduxState: reduxStore.getState() } }
}
export default Home
How to call a callback function?
Or how to set state after mapStateToProps get data?
RegistrationContainers:
function mapStateToProps(state, props) {
return {
isRegistered: state.user.registered // isRegistered: 1
};
function mapDispatchToProps(dispatch, props) {
return {
registration:(data) => dispatch(registration(data))
};
RegistrationComponents:
onRegister(){
let email = this.state.email;
let password = this.state.password;
let registerData = {email:email,password:password};
registerData = JSON.stringify(registerData);
this.props.registration(registerData)
this.setState({isRegistered: this.props.isRegistered}) // isRegistered: undefined, but second run after is correct
registration actions:
export function OnRegistration(registered) {
/* ... */
return registered }
export function registration(regData) {
return (dispatch) => {
sendDataToApi(regData, "registration",(isRegistered)=>{
dispatch({
type: ON_REGISTRATION,
registered: isRegistered
})
})
}
}
registration reducer:
const initialState = {};
export function loginReducer(state = initialState, action) {
switch(action.type){
case REGISTRATION:
return Object.assign({},state,{
registered: action.registered
})
}
return state; }
Containers get current state, but containers props can't reach from components.
modify your methods by adding callback() functions. i.e.
function mapDispatchToProps(dispatch, props) {
return {
registration:(data, cb = null) => dispatch(registration(data, cb))
};
and modify registration(data) method to:
registration(data, cb) {
/* your code here */
/* on successful registration, set user.registered to true in redux and
then call cb function */
cb && cb();
}
modify onRegister() method to:
onRegister(){
let email = this.state.email;
let password = this.state.password;
let registerData = {email:email,password:password};
registerData = JSON.stringify(registerData);
this.props.registration(registerData, () => {
this.setState({isRegistered: this.props.isRegistered})
}
})
Need display data after AJAX call will be done.
My Reducer:
import { INCOME_PROFILE } from '../actionTypes'
import Immutable from 'immutable'
const initialUserState = [];
const profileReducer = function(state = initialUserState, action) {
//console.log('actiondata in reducer:' + action.data + action.type);
switch(action.type) {
case 'INCOME_PROFILE_IS_LOADING':
return Object.assign({}, state, { hh: action.hasFetched });
case 'INCOME_PROFILE':
return Object.assign({}, state, { course_list: action.data, hh: action.hasFetched });
default:
return state;
}
}
export default profileReducer
My action creator:
export function GET_ITEM_REQUEST() {
return {
type: INCOME_PROFILE_IS_LOADING,
hasFetched: false,
}
}
function receiveData(json) {
return{
type: INCOME_PROFILE,
data: json,
hasFetched: true
}
};
export function IncomeProfileList () {
return dispatch => {
return (
axios.post(Api.getURI("profile"),{}, {
headers: { 'X-Authenticated-Userid': '15000500000#1' }
}).then(function (response) {
//console.log(response.data);
dispatch(receiveData(response.data.body));
})
.catch((error) => {
console.log(error);
})
)
}
}
My component:
class IncomeProfile extends Component {
constructor(props) {
super(props)
}
componentDidMount() {
this.props.IncomeListProfile();
}
render() {
console.log(this.props.isloading);
if (this.props.isloading) {
return <p>Sorry! There was an error loading the items</p>;
}
}
}
const mapDispatchToProps = function(dispatch) {
return {
IncomeListProfile: () => dispatch(IncomeProfileList())
}
}
const mapStateToProps = function(state) {
//var mystore = state.toJS()
var mystore = state.getIn(['incomeProfileList'])['course_list'];
var mystored = state.getIn(['incomeProfileList']);
console.log(mystored.hh);
var copy = Object.assign({}, mystore);
return {
items: copy.course_list,
isloading: mystored.hh
};
}
I need next: While response not finish, I no need to display data. Condition if not works now
console.log at first time get undefined - think must be false, but it not state false. and second time it's getting true.
You don't need property 'isLoading' - just handle 2 cases in which you have your data and you haven't. Put this condition in render() function, because the component is going to refresh after passing data through the reducer. Syntax will be something like this in your case:
render() {
if(!this.props.items) {
return <div>Loading...</div>;
} else {
return (
<div>Display your data!</div>
);
}
}
Whenever my 'COLLEGE_ADDED' action is dispatched I can see the state changes in the reducer. However the update related lifecycle methods on the CollegeSearchList component and it's children aren't being called. These components aren't re-rendering presumably because of this.
I have read the docs about not mutating state and I don't think I am. Complete code can be found here https://github.com/tlatkinson/react-search-widget.
components/search/college/CollegeSearchList.js
class CollegeSearchList extends Component {
componentWillUpdate (nextProps, nextState) {
console.log(nextProps.searchItems);
console.log(nextState);
return true;
}
render () {
return (
<SearchList searchItems={this.props.searchItems} SearchListItem={CollegeSearchListItem} />
)
}
}
const mapStateToProps = (state, {id}) => {
return {
searchItems: getSearchResultsById(state.searchState, id),
SearchListItem: CollegeSearchListItem,
}
};
CollegeSearchList = connect(
mapStateToProps
)(CollegeSearchList);
reducers/search.js
const searchReducer = (searchState = [], action) => {
switch(action.type) {
case 'COLLEGE_SEARCH':
return mergeData(searchState, action, 'college', 'phrase');
case 'COLLEGE_SEARCH_SUCCESS':
return mergeData(searchState, action, 'college', 'searchResults');
case 'COLLEGE_ADDED':
return updateCollegeAdded(searchState, action.collegeId, true);
case 'COLLEGE_REMOVED':
return updateCollegeAdded(searchState, action.collegeId, false);
default:
return searchState;
}
};
export default searchReducer
const updateCollegeAdded = (searchState, collegeId, added) => {
const newState = {...searchState};
for (let id of Object.keys(newState)) {
const searchComponent = searchState[id];
if(searchComponent.searchType === 'college') {
searchComponent.searchResults.forEach(searchResult => {
if(searchResult.id === collegeId) {
searchResult.added = added;
}
});
}
}
return newState;
};
const mergeData = (data, action, searchType, propertyModified) => {
return {
...data,
[action.id]: {
searchType,
...data[action.id],
[propertyModified]: action[propertyModified],
}
};
};
actions/index.js
export const addRemoveCollege = (collegeId, collegeName, addToList) => (dispatch) => {
if (addToList) {
api.addToCollegeList(collegeId)
.then(() => {
dispatch({
type: 'COLLEGE_ADDED',
collegeId,
collegeName,
});
})
} else {
api.removeFromCollegeList(collegeId)
.then(() => {
dispatch({
type: 'COLLEGE_REMOVED',
collegeId,
collegeName,
});
})
}
};