简体   繁体   中英

How to use React Redux store in component that modifies and renders the state

In Text component, I want to get text_data from DB once and save it to the Redux store.


export default function Text() {

  const [document, setDocument] = useState([]);
  setDocument(useSelector(currentState))

  useEffect(() => {
    axios.get(`/api/texts/${docId}`).then((response) => {
      dispatch(currentState(response.data));
    })
  }, [])
  return (
    <div className="Text">
        {document.text && document.text.map((text, index) => (
          <div onClick={() => {dispatch(changeColor(index))}}>
            {text.word}
          </div>
        ))}
    </div>
  )
}

Then I'd like to get the text_data from Redux store probably in the same component

  setDocument(useSelector(currentState))

But it causes infinite rerender.

Moreover, I'd like to modify the text_data with clicks so that Text component will show text in different colors after click. For that, I'd like to modify Redux state and rerender Text component.

text_data has a structure {word: color, second_word: color, ...}

How to use Redux for that? Is it possible, is my thinking correct that the redux state should be the only one thing that should change?

EDIT: Code snippet added. I am working on this so my code snippet doesn't work.

I think you are not understand react-redux hooks correctly. These two lines does not make sense. I don't know what your currentState variable should be in your snippet. But the usage is definitely wrong.

setDocument(useSelector(currentState))
dispatch(currentState(response.data));

I don't know what your redux store looks like. In next snippets I will assume that it is something like this.

// redux store structure
{
  texts: {document: {}, coloredWords: {}}
}

// fetched document will have structure something like this (array of words)
{text: []}

Your (texts) reducer should modified the redux store like this (written just schematically)

// ...

// storing fetched document
case 'SET_DOCUMENT': {
  const document = action.payload
  return {...state, document: document}
}

// storing color for word at particular index
case 'CHANGE_COLOR': {
  const {index, color} = action.payload
  return {...state, coloredWords: {...state.coloredWords, [index]: color}}
}

// ...
import { useDispatch, useSelector } from 'react-redux'

import { setDocument, changeColor } from 'path_to_file_with_action_creators'

export default function Text() {  
  const dispatch = useDispatch()
  // get fetched document from your redux store (it will be an empty object in the first render, while fetch in the useEffect hook is called after the first render)
  const document = useSelector(state => state.texts.document))
  // get colors for document words (they were saved in redux store by your onClick handler, see bellow)
  const coloredWords = useSelector(state => state.texts.coloredWords))

  useEffect(() => {
    // fetch document
    axios.get(`/api/texts/${docId}`).then((response) => {
      // store fetched document in your redux store
      dispatch(setDocument(response.data));
    })
  }, [])
  return (
    <div className="Text">
        {document && document.text && document.text.map((text, index) => (
          <div
            style={{color: coloredWords[index] ? coloredWords[index] : 'black' }}
            onClick={() => {
              // store color for word at particular index in redux store
              dispatch(changeColor({index: index, color: 'red'}))
            }}
          >
            {text.word}
          </div>
        ))}
    </div>
  )
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM